@automate.ax/integration-contracts 0.148.0 → 0.150.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/dist/calcom/events.d.ts +1067 -11
- package/dist/calcom/events.js +66 -32
- package/dist/kit/schemas.js +57 -0
- package/dist/kit/types.d.ts +7 -1
- package/dist/krisp/api.d.ts +61 -0
- package/dist/krisp/api.js +170 -0
- package/dist/krisp/index.d.ts +2 -0
- package/dist/krisp/index.js +2 -0
- package/dist/krisp/schemas.d.ts +145 -0
- package/dist/krisp/schemas.js +97 -0
- package/package.json +8 -2
- package/src/calcom/events.ts +149 -30
- package/src/kit/schemas.ts +64 -0
- package/src/kit/types.ts +15 -1
- package/src/krisp/api.ts +215 -0
- package/src/krisp/index.ts +2 -0
- package/src/krisp/schemas.ts +122 -0
package/dist/calcom/events.js
CHANGED
|
@@ -287,7 +287,40 @@ const CALCOM_PAYLOAD_SCHEMAS = {
|
|
|
287
287
|
}),
|
|
288
288
|
}),
|
|
289
289
|
};
|
|
290
|
-
export const
|
|
290
|
+
export const CALCOM_USER_WEBHOOK_SCOPE_SCHEMA = z.object({
|
|
291
|
+
type: z.literal("user"),
|
|
292
|
+
});
|
|
293
|
+
export const CALCOM_TEAM_WEBHOOK_SCOPE_SCHEMA = z.object({
|
|
294
|
+
eventTypeId: z.number().int().positive(),
|
|
295
|
+
teamId: z.number().int().positive(),
|
|
296
|
+
type: z.literal("team"),
|
|
297
|
+
});
|
|
298
|
+
export const CALCOM_ORGANIZATION_WEBHOOK_SCOPE_SCHEMA = z.object({
|
|
299
|
+
organizationId: z.number().int().positive(),
|
|
300
|
+
type: z.literal("organization"),
|
|
301
|
+
});
|
|
302
|
+
export const CALCOM_WEBHOOK_SCOPE_SCHEMA = z.discriminatedUnion("type", [
|
|
303
|
+
CALCOM_USER_WEBHOOK_SCOPE_SCHEMA,
|
|
304
|
+
CALCOM_TEAM_WEBHOOK_SCOPE_SCHEMA,
|
|
305
|
+
CALCOM_ORGANIZATION_WEBHOOK_SCOPE_SCHEMA,
|
|
306
|
+
]);
|
|
307
|
+
export const CALCOM_USER_TRIGGER_CONFIG_SCHEMA = z.object({
|
|
308
|
+
scope: CALCOM_USER_WEBHOOK_SCOPE_SCHEMA.optional(),
|
|
309
|
+
});
|
|
310
|
+
export const CALCOM_TEAM_TRIGGER_CONFIG_SCHEMA = z.object({
|
|
311
|
+
scope: z
|
|
312
|
+
.discriminatedUnion("type", [
|
|
313
|
+
CALCOM_USER_WEBHOOK_SCOPE_SCHEMA,
|
|
314
|
+
CALCOM_TEAM_WEBHOOK_SCOPE_SCHEMA,
|
|
315
|
+
])
|
|
316
|
+
.optional(),
|
|
317
|
+
});
|
|
318
|
+
export const CALCOM_ORGANIZATION_TRIGGER_CONFIG_SCHEMA = z.object({
|
|
319
|
+
scope: CALCOM_ORGANIZATION_WEBHOOK_SCOPE_SCHEMA,
|
|
320
|
+
});
|
|
321
|
+
export const CALCOM_BROAD_TRIGGER_CONFIG_SCHEMA = z.object({
|
|
322
|
+
scope: CALCOM_WEBHOOK_SCOPE_SCHEMA.optional(),
|
|
323
|
+
});
|
|
291
324
|
export const CALCOM_EVENT_SCHEMA = z.custom((value) => {
|
|
292
325
|
if (typeof value !== "object" ||
|
|
293
326
|
value === null ||
|
|
@@ -368,47 +401,48 @@ export const CALCOM_EVENT_TYPE_MAP = {
|
|
|
368
401
|
WRONG_ASSIGNMENT_REPORT: "calcom.wrongAssignmentReported",
|
|
369
402
|
};
|
|
370
403
|
export const calcomTriggerContracts = {
|
|
371
|
-
"calcom.afterGuestsCalVideoNoShow": contract("AFTER_GUESTS_CAL_VIDEO_NO_SHOW"),
|
|
372
|
-
"calcom.afterHostsCalVideoNoShow": contract("AFTER_HOSTS_CAL_VIDEO_NO_SHOW"),
|
|
373
|
-
"calcom.booking.cancelled": contract("BOOKING_CANCELLED"),
|
|
374
|
-
"calcom.booking.created": contract("BOOKING_CREATED"),
|
|
375
|
-
"calcom.booking.locationUpdated": contract("BOOKING_LOCATION_UPDATED"),
|
|
376
|
-
"calcom.booking.noShowUpdated": contract("BOOKING_NO_SHOW_UPDATED"),
|
|
377
|
-
"calcom.booking.paid": contract("BOOKING_PAID"),
|
|
378
|
-
"calcom.booking.paymentInitiated": contract("BOOKING_PAYMENT_INITIATED"),
|
|
379
|
-
"calcom.booking.reassigned": contract("BOOKING_REASSIGNED"),
|
|
380
|
-
"calcom.booking.rejected": contract("BOOKING_REJECTED"),
|
|
381
|
-
"calcom.booking.requested": contract("BOOKING_REQUESTED"),
|
|
382
|
-
"calcom.booking.rescheduled": contract("BOOKING_RESCHEDULED"),
|
|
383
|
-
"calcom.calendarEntryRejected": contract("CALENDAR_ENTRY_REJECTED"),
|
|
384
|
-
"calcom.delegationCredential.error": contract("DELEGATION_CREDENTIAL_ERROR"),
|
|
385
|
-
"calcom.delegationCredential.rotationRequired": contract("DELEGATION_CREDENTIAL_ROTATION_REQUIRED"),
|
|
386
|
-
"calcom.delegationCredential.secretRotated": contract("DELEGATION_CREDENTIAL_SECRET_ROTATED"),
|
|
387
|
-
"calcom.delegationCredential.secretRotationFailed": contract("DELEGATION_CREDENTIAL_SECRET_ROTATION_FAILED"),
|
|
404
|
+
"calcom.afterGuestsCalVideoNoShow": contract("AFTER_GUESTS_CAL_VIDEO_NO_SHOW", CALCOM_USER_TRIGGER_CONFIG_SCHEMA),
|
|
405
|
+
"calcom.afterHostsCalVideoNoShow": contract("AFTER_HOSTS_CAL_VIDEO_NO_SHOW", CALCOM_USER_TRIGGER_CONFIG_SCHEMA),
|
|
406
|
+
"calcom.booking.cancelled": contract("BOOKING_CANCELLED", CALCOM_TEAM_TRIGGER_CONFIG_SCHEMA),
|
|
407
|
+
"calcom.booking.created": contract("BOOKING_CREATED", CALCOM_TEAM_TRIGGER_CONFIG_SCHEMA),
|
|
408
|
+
"calcom.booking.locationUpdated": contract("BOOKING_LOCATION_UPDATED", CALCOM_TEAM_TRIGGER_CONFIG_SCHEMA),
|
|
409
|
+
"calcom.booking.noShowUpdated": contract("BOOKING_NO_SHOW_UPDATED", CALCOM_TEAM_TRIGGER_CONFIG_SCHEMA),
|
|
410
|
+
"calcom.booking.paid": contract("BOOKING_PAID", CALCOM_TEAM_TRIGGER_CONFIG_SCHEMA),
|
|
411
|
+
"calcom.booking.paymentInitiated": contract("BOOKING_PAYMENT_INITIATED", CALCOM_TEAM_TRIGGER_CONFIG_SCHEMA),
|
|
412
|
+
"calcom.booking.reassigned": contract("BOOKING_REASSIGNED", CALCOM_TEAM_TRIGGER_CONFIG_SCHEMA),
|
|
413
|
+
"calcom.booking.rejected": contract("BOOKING_REJECTED", CALCOM_TEAM_TRIGGER_CONFIG_SCHEMA),
|
|
414
|
+
"calcom.booking.requested": contract("BOOKING_REQUESTED", CALCOM_TEAM_TRIGGER_CONFIG_SCHEMA),
|
|
415
|
+
"calcom.booking.rescheduled": contract("BOOKING_RESCHEDULED", CALCOM_TEAM_TRIGGER_CONFIG_SCHEMA),
|
|
416
|
+
"calcom.calendarEntryRejected": contract("CALENDAR_ENTRY_REJECTED", CALCOM_USER_TRIGGER_CONFIG_SCHEMA),
|
|
417
|
+
"calcom.delegationCredential.error": contract("DELEGATION_CREDENTIAL_ERROR", CALCOM_ORGANIZATION_TRIGGER_CONFIG_SCHEMA),
|
|
418
|
+
"calcom.delegationCredential.rotationRequired": contract("DELEGATION_CREDENTIAL_ROTATION_REQUIRED", CALCOM_ORGANIZATION_TRIGGER_CONFIG_SCHEMA),
|
|
419
|
+
"calcom.delegationCredential.secretRotated": contract("DELEGATION_CREDENTIAL_SECRET_ROTATED", CALCOM_ORGANIZATION_TRIGGER_CONFIG_SCHEMA),
|
|
420
|
+
"calcom.delegationCredential.secretRotationFailed": contract("DELEGATION_CREDENTIAL_SECRET_ROTATION_FAILED", CALCOM_ORGANIZATION_TRIGGER_CONFIG_SCHEMA),
|
|
388
421
|
"calcom.event": {
|
|
389
|
-
configSchema:
|
|
422
|
+
configSchema: CALCOM_BROAD_TRIGGER_CONFIG_SCHEMA,
|
|
390
423
|
eventSchema: CALCOM_EVENT_SCHEMA,
|
|
391
424
|
},
|
|
392
|
-
"calcom.form.submitted": contract("FORM_SUBMITTED"),
|
|
393
|
-
"calcom.form.submittedWithoutEvent": contract("FORM_SUBMITTED_NO_EVENT"),
|
|
394
|
-
"calcom.instantMeeting.accepted": contract("INSTANT_MEETING_ACCEPTED"),
|
|
395
|
-
"calcom.instantMeeting.created": contract("INSTANT_MEETING"),
|
|
396
|
-
"calcom.meeting.ended": contract("MEETING_ENDED"),
|
|
397
|
-
"calcom.meeting.started": contract("MEETING_STARTED"),
|
|
398
|
-
"calcom.outOfOffice.created": contract("OOO_CREATED"),
|
|
399
|
-
"calcom.recording.ready": contract("RECORDING_READY"),
|
|
400
|
-
"calcom.recording.transcriptionGenerated": contract("RECORDING_TRANSCRIPTION_GENERATED"),
|
|
401
|
-
"calcom.routingForm.fallbackHit": contract("ROUTING_FORM_FALLBACK_HIT"),
|
|
402
|
-
"calcom.wrongAssignmentReported": contract("WRONG_ASSIGNMENT_REPORT"),
|
|
425
|
+
"calcom.form.submitted": contract("FORM_SUBMITTED", CALCOM_USER_TRIGGER_CONFIG_SCHEMA),
|
|
426
|
+
"calcom.form.submittedWithoutEvent": contract("FORM_SUBMITTED_NO_EVENT", CALCOM_USER_TRIGGER_CONFIG_SCHEMA),
|
|
427
|
+
"calcom.instantMeeting.accepted": contract("INSTANT_MEETING_ACCEPTED", CALCOM_USER_TRIGGER_CONFIG_SCHEMA),
|
|
428
|
+
"calcom.instantMeeting.created": contract("INSTANT_MEETING", CALCOM_USER_TRIGGER_CONFIG_SCHEMA),
|
|
429
|
+
"calcom.meeting.ended": contract("MEETING_ENDED", CALCOM_USER_TRIGGER_CONFIG_SCHEMA),
|
|
430
|
+
"calcom.meeting.started": contract("MEETING_STARTED", CALCOM_USER_TRIGGER_CONFIG_SCHEMA),
|
|
431
|
+
"calcom.outOfOffice.created": contract("OOO_CREATED", CALCOM_USER_TRIGGER_CONFIG_SCHEMA),
|
|
432
|
+
"calcom.recording.ready": contract("RECORDING_READY", CALCOM_USER_TRIGGER_CONFIG_SCHEMA),
|
|
433
|
+
"calcom.recording.transcriptionGenerated": contract("RECORDING_TRANSCRIPTION_GENERATED", CALCOM_USER_TRIGGER_CONFIG_SCHEMA),
|
|
434
|
+
"calcom.routingForm.fallbackHit": contract("ROUTING_FORM_FALLBACK_HIT", CALCOM_USER_TRIGGER_CONFIG_SCHEMA),
|
|
435
|
+
"calcom.wrongAssignmentReported": contract("WRONG_ASSIGNMENT_REPORT", CALCOM_USER_TRIGGER_CONFIG_SCHEMA),
|
|
403
436
|
};
|
|
404
437
|
/**
|
|
405
438
|
* Builds one trigger contract for an exact Cal.com provider event.
|
|
406
439
|
*
|
|
407
440
|
* @param type Exact Cal.com provider event type.
|
|
441
|
+
* @param configSchema Trigger configuration schema.
|
|
408
442
|
*/
|
|
409
|
-
function contract(type) {
|
|
443
|
+
function contract(type, configSchema) {
|
|
410
444
|
return {
|
|
411
|
-
configSchema
|
|
445
|
+
configSchema,
|
|
412
446
|
eventSchema: calcomSemanticEventSchema(type),
|
|
413
447
|
};
|
|
414
448
|
}
|
package/dist/kit/schemas.js
CHANGED
|
@@ -4,6 +4,13 @@ import * as z from "zod";
|
|
|
4
4
|
import { KIT_OPENAPI_DATA } from "./openapi-operations.generated";
|
|
5
5
|
/** Runtime Kit contract narrowed once from the opaque generated payload. */
|
|
6
6
|
const operationData = KIT_OPENAPI_DATA;
|
|
7
|
+
for (const operation of Object.values(operationData.operations)) {
|
|
8
|
+
if (typeof operation !== "object" || operation === null)
|
|
9
|
+
continue;
|
|
10
|
+
const record = operation;
|
|
11
|
+
normalizeObservedKitNulls(record.outputSchema);
|
|
12
|
+
normalizeObservedKitNulls(record.outputWireSchema);
|
|
13
|
+
}
|
|
7
14
|
const OPERATIONS = operationData.operations;
|
|
8
15
|
const VALIDATOR = new Validator({
|
|
9
16
|
$defs: operationData.definitions,
|
|
@@ -41,3 +48,53 @@ export function kitOperationOutputSchema(key) {
|
|
|
41
48
|
}
|
|
42
49
|
/** Provider-native component schemas used for schema-guided key mapping. */
|
|
43
50
|
export const KIT_WIRE_DEFINITIONS = operationData.wireDefinitions;
|
|
51
|
+
/**
|
|
52
|
+
* Accepts nullable fields observed in successful Kit responses but omitted from
|
|
53
|
+
* the provider's OpenAPI nullability metadata.
|
|
54
|
+
*
|
|
55
|
+
* @param value Generated operation metadata.
|
|
56
|
+
*/
|
|
57
|
+
function normalizeObservedKitNulls(value) {
|
|
58
|
+
if (Array.isArray(value)) {
|
|
59
|
+
for (const item of value)
|
|
60
|
+
normalizeObservedKitNulls(item);
|
|
61
|
+
return;
|
|
62
|
+
}
|
|
63
|
+
if (typeof value !== "object" || value === null)
|
|
64
|
+
return;
|
|
65
|
+
const record = value;
|
|
66
|
+
const properties = record.properties;
|
|
67
|
+
if (typeof properties === "object" && properties !== null) {
|
|
68
|
+
const propertyRecord = properties;
|
|
69
|
+
for (const name of [
|
|
70
|
+
"bio",
|
|
71
|
+
"byline",
|
|
72
|
+
"endCursor",
|
|
73
|
+
"end_cursor",
|
|
74
|
+
"startCursor",
|
|
75
|
+
"start_cursor",
|
|
76
|
+
]) {
|
|
77
|
+
const property = propertyRecord[name];
|
|
78
|
+
if (typeof property !== "object" ||
|
|
79
|
+
property === null ||
|
|
80
|
+
isNullableSchema(property)) {
|
|
81
|
+
continue;
|
|
82
|
+
}
|
|
83
|
+
propertyRecord[name] = { anyOf: [property, { type: "null" }] };
|
|
84
|
+
}
|
|
85
|
+
}
|
|
86
|
+
for (const child of Object.values(record))
|
|
87
|
+
normalizeObservedKitNulls(child);
|
|
88
|
+
}
|
|
89
|
+
/**
|
|
90
|
+
* Returns whether one JSON Schema fragment already accepts null.
|
|
91
|
+
*
|
|
92
|
+
* @param value JSON Schema fragment.
|
|
93
|
+
*/
|
|
94
|
+
function isNullableSchema(value) {
|
|
95
|
+
const anyOf = value.anyOf;
|
|
96
|
+
return (Array.isArray(anyOf) &&
|
|
97
|
+
anyOf.some((branch) => typeof branch === "object" &&
|
|
98
|
+
branch !== null &&
|
|
99
|
+
branch.type === "null"));
|
|
100
|
+
}
|
package/dist/kit/types.d.ts
CHANGED
|
@@ -28,6 +28,12 @@ type Simplify<TValue> = {
|
|
|
28
28
|
type EncodableValue<TValue> = unknown extends TValue ? Encodable : TValue extends undefined | null | boolean | number | string ? TValue : TValue extends readonly (infer TItem)[] ? EncodableValue<TItem>[] : TValue extends object ? keyof TValue extends never ? Record<string, Encodable> : {
|
|
29
29
|
[TKey in keyof TValue]: EncodableValue<TValue[TKey]>;
|
|
30
30
|
} : never;
|
|
31
|
+
/** Fields whose live Kit nullability is missing from its OpenAPI document. */
|
|
32
|
+
type ObservedNullableField = "bio" | "byline" | "endCursor" | "startCursor";
|
|
33
|
+
/** Adds nulls returned by Kit but omitted from its generated OpenAPI types. */
|
|
34
|
+
type NormalizeObservedKitNulls<TValue> = TValue extends readonly (infer TItem)[] ? NormalizeObservedKitNulls<TItem>[] : TValue extends object ? {
|
|
35
|
+
[TKey in keyof TValue]: NormalizeObservedKitNulls<TValue[TKey]> | (TKey extends ObservedNullableField ? null : never);
|
|
36
|
+
} : TValue;
|
|
31
37
|
/** Flattens one generated operation's path, query, and body fields. */
|
|
32
38
|
type RawKitOperationInput<TKey extends KitOperationKey> = Simplify<Parameters<Operation<TKey>, "path"> & Parameters<Operation<TKey>, "query"> & JsonBody<Operation<TKey>>>;
|
|
33
39
|
/** Preserves operation unions and rejects fields on truly empty inputs. */
|
|
@@ -37,5 +43,5 @@ type PublicInput<TValue> = TValue extends unknown ? keyof TValue extends never ?
|
|
|
37
43
|
/** Flattened camelCase input for one frozen Kit V4 operation. */
|
|
38
44
|
export type KitOperationInput<TKey extends KitOperationKey> = PublicInput<RawKitOperationInput<TKey>>;
|
|
39
45
|
/** CamelCase successful response for one frozen Kit V4 operation. */
|
|
40
|
-
export type KitOperationOutput<TKey extends KitOperationKey> = EncodableValue<SuccessResponse<Operation<TKey
|
|
46
|
+
export type KitOperationOutput<TKey extends KitOperationKey> = EncodableValue<NormalizeObservedKitNulls<SuccessResponse<Operation<TKey>>>>;
|
|
41
47
|
export {};
|
|
@@ -0,0 +1,61 @@
|
|
|
1
|
+
import type { Encodable } from "@automate.ax/codec";
|
|
2
|
+
import * as z from "zod";
|
|
3
|
+
/** Options for one authenticated Krisp REST request. */
|
|
4
|
+
export interface KrispRequestOptions<TSchema extends z.ZodType> {
|
|
5
|
+
/** Public camelCase JSON body. */
|
|
6
|
+
body?: Encodable;
|
|
7
|
+
/** HTTP verb. Defaults to `GET`. */
|
|
8
|
+
method?: "GET" | "POST";
|
|
9
|
+
/** Public camelCase query parameters. */
|
|
10
|
+
query?: Record<string, boolean | number | readonly string[] | string | undefined>;
|
|
11
|
+
/** Schema for the normalized provider response. */
|
|
12
|
+
responseSchema: TSchema;
|
|
13
|
+
}
|
|
14
|
+
/** Structured Krisp REST failure. */
|
|
15
|
+
export declare class KrispApiError extends Error {
|
|
16
|
+
/** Normalized provider error payload, when valid JSON was returned. */
|
|
17
|
+
readonly body?: Encodable;
|
|
18
|
+
/** Retry delay in seconds, when Krisp returned one. */
|
|
19
|
+
readonly retryAfter?: number;
|
|
20
|
+
/** HTTP status returned by Krisp. */
|
|
21
|
+
readonly status: number;
|
|
22
|
+
/**
|
|
23
|
+
* Creates a structured Krisp API error.
|
|
24
|
+
*
|
|
25
|
+
* @param options - Provider status, body, and retry metadata.
|
|
26
|
+
* @param options.body - Normalized provider error body.
|
|
27
|
+
* @param options.retryAfter - Retry delay in seconds.
|
|
28
|
+
* @param options.status - HTTP status.
|
|
29
|
+
*/
|
|
30
|
+
constructor(options: {
|
|
31
|
+
body?: Encodable;
|
|
32
|
+
retryAfter?: number;
|
|
33
|
+
status: number;
|
|
34
|
+
});
|
|
35
|
+
}
|
|
36
|
+
/**
|
|
37
|
+
* Creates an authenticated Krisp Meeting Assistant REST client.
|
|
38
|
+
*
|
|
39
|
+
* @param secret - Resolved Krisp API-key secret.
|
|
40
|
+
*/
|
|
41
|
+
export declare function getKrispApi(secret: Record<string, unknown>): {
|
|
42
|
+
/**
|
|
43
|
+
* Runs one Krisp request and returns its normalized response.
|
|
44
|
+
*
|
|
45
|
+
* @param path - API path relative to the v1 root.
|
|
46
|
+
* @param options - Method, parameters, and response schema.
|
|
47
|
+
*/
|
|
48
|
+
request<TSchema extends z.ZodType>(path: string, options: KrispRequestOptions<TSchema>): Promise<z.output<TSchema>>;
|
|
49
|
+
};
|
|
50
|
+
/**
|
|
51
|
+
* Converts public camelCase JSON to Krisp wire keys.
|
|
52
|
+
*
|
|
53
|
+
* @param value - Public value to normalize.
|
|
54
|
+
*/
|
|
55
|
+
export declare function toKrisp(value: Encodable): Encodable;
|
|
56
|
+
/**
|
|
57
|
+
* Converts Krisp wire JSON to public camelCase keys.
|
|
58
|
+
*
|
|
59
|
+
* @param value - Provider value to normalize.
|
|
60
|
+
*/
|
|
61
|
+
export declare function fromKrisp(value: unknown): unknown;
|
|
@@ -0,0 +1,170 @@
|
|
|
1
|
+
import { encodableSchema } from "@automate.ax/codec";
|
|
2
|
+
import * as z from "zod";
|
|
3
|
+
const KRISP_API_BASE_URL = "https://meeting-api.krisp.ai/v1/";
|
|
4
|
+
const KRISP_API_ORIGIN = new URL(KRISP_API_BASE_URL).origin;
|
|
5
|
+
const KRISP_SECRET_SCHEMA = z.object({ apiKey: z.string().min(1) });
|
|
6
|
+
/** Structured Krisp REST failure. */
|
|
7
|
+
export class KrispApiError extends Error {
|
|
8
|
+
/** Normalized provider error payload, when valid JSON was returned. */
|
|
9
|
+
body;
|
|
10
|
+
/** Retry delay in seconds, when Krisp returned one. */
|
|
11
|
+
retryAfter;
|
|
12
|
+
/** HTTP status returned by Krisp. */
|
|
13
|
+
status;
|
|
14
|
+
/**
|
|
15
|
+
* Creates a structured Krisp API error.
|
|
16
|
+
*
|
|
17
|
+
* @param options - Provider status, body, and retry metadata.
|
|
18
|
+
* @param options.body - Normalized provider error body.
|
|
19
|
+
* @param options.retryAfter - Retry delay in seconds.
|
|
20
|
+
* @param options.status - HTTP status.
|
|
21
|
+
*/
|
|
22
|
+
constructor(options) {
|
|
23
|
+
super(getErrorMessage(options.body) ??
|
|
24
|
+
`Krisp API request failed with status ${options.status}.`);
|
|
25
|
+
this.name = "KrispApiError";
|
|
26
|
+
this.body = options.body;
|
|
27
|
+
this.retryAfter = options.retryAfter;
|
|
28
|
+
this.status = options.status;
|
|
29
|
+
}
|
|
30
|
+
}
|
|
31
|
+
/**
|
|
32
|
+
* Creates an authenticated Krisp Meeting Assistant REST client.
|
|
33
|
+
*
|
|
34
|
+
* @param secret - Resolved Krisp API-key secret.
|
|
35
|
+
*/
|
|
36
|
+
export function getKrispApi(secret) {
|
|
37
|
+
const { apiKey } = KRISP_SECRET_SCHEMA.parse(secret);
|
|
38
|
+
return {
|
|
39
|
+
/**
|
|
40
|
+
* Runs one Krisp request and returns its normalized response.
|
|
41
|
+
*
|
|
42
|
+
* @param path - API path relative to the v1 root.
|
|
43
|
+
* @param options - Method, parameters, and response schema.
|
|
44
|
+
*/
|
|
45
|
+
async request(path, options) {
|
|
46
|
+
const url = new URL(path.replace(/^\//, ""), KRISP_API_BASE_URL);
|
|
47
|
+
if (url.origin !== KRISP_API_ORIGIN) {
|
|
48
|
+
throw new Error("Krisp API paths must use the Krisp API origin.");
|
|
49
|
+
}
|
|
50
|
+
for (const [name, value] of Object.entries(options.query ?? {})) {
|
|
51
|
+
if (value === undefined)
|
|
52
|
+
continue;
|
|
53
|
+
url.searchParams.set(toSnakeCase(name), Array.isArray(value) ? value.join(",") : String(value));
|
|
54
|
+
}
|
|
55
|
+
const response = await fetch(url, {
|
|
56
|
+
body: options.body === undefined
|
|
57
|
+
? undefined
|
|
58
|
+
: JSON.stringify(toKrisp(options.body)),
|
|
59
|
+
headers: {
|
|
60
|
+
Accept: "application/json",
|
|
61
|
+
Authorization: `Bearer ${apiKey}`,
|
|
62
|
+
...(options.body === undefined
|
|
63
|
+
? {}
|
|
64
|
+
: { "Content-Type": "application/json" }),
|
|
65
|
+
},
|
|
66
|
+
method: options.method ?? "GET",
|
|
67
|
+
});
|
|
68
|
+
const normalized = fromKrisp(parseJson(await response.text()));
|
|
69
|
+
if (!response.ok) {
|
|
70
|
+
const body = encodableSchema.safeParse(normalized);
|
|
71
|
+
throw new KrispApiError({
|
|
72
|
+
...(body.success && { body: body.data }),
|
|
73
|
+
retryAfter: parseFiniteNumber(response.headers.get("Retry-After")),
|
|
74
|
+
status: response.status,
|
|
75
|
+
});
|
|
76
|
+
}
|
|
77
|
+
return options.responseSchema.parse(normalized);
|
|
78
|
+
},
|
|
79
|
+
};
|
|
80
|
+
}
|
|
81
|
+
/**
|
|
82
|
+
* Converts public camelCase JSON to Krisp wire keys.
|
|
83
|
+
*
|
|
84
|
+
* @param value - Public value to normalize.
|
|
85
|
+
*/
|
|
86
|
+
export function toKrisp(value) {
|
|
87
|
+
if (value instanceof Date)
|
|
88
|
+
return value.toISOString();
|
|
89
|
+
if (Array.isArray(value))
|
|
90
|
+
return value.map(toKrisp);
|
|
91
|
+
if (!isPlainObject(value))
|
|
92
|
+
return value;
|
|
93
|
+
return Object.fromEntries(Object.entries(value).map(([key, item]) => [
|
|
94
|
+
toSnakeCase(key),
|
|
95
|
+
toKrisp(item),
|
|
96
|
+
]));
|
|
97
|
+
}
|
|
98
|
+
/**
|
|
99
|
+
* Converts Krisp wire JSON to public camelCase keys.
|
|
100
|
+
*
|
|
101
|
+
* @param value - Provider value to normalize.
|
|
102
|
+
*/
|
|
103
|
+
export function fromKrisp(value) {
|
|
104
|
+
if (Array.isArray(value))
|
|
105
|
+
return value.map(fromKrisp);
|
|
106
|
+
if (!isPlainObject(value))
|
|
107
|
+
return value;
|
|
108
|
+
return Object.fromEntries(Object.entries(value).map(([key, item]) => [
|
|
109
|
+
toCamelCase(key),
|
|
110
|
+
fromKrisp(item),
|
|
111
|
+
]));
|
|
112
|
+
}
|
|
113
|
+
/**
|
|
114
|
+
* Checks whether a value is a key-value object.
|
|
115
|
+
*
|
|
116
|
+
* @param value - Candidate value.
|
|
117
|
+
*/
|
|
118
|
+
function isPlainObject(value) {
|
|
119
|
+
return typeof value === "object" && value !== null && !Array.isArray(value);
|
|
120
|
+
}
|
|
121
|
+
/**
|
|
122
|
+
* Parses a JSON response body without obscuring the HTTP status on failure.
|
|
123
|
+
*
|
|
124
|
+
* @param value - Raw response text.
|
|
125
|
+
*/
|
|
126
|
+
function parseJson(value) {
|
|
127
|
+
try {
|
|
128
|
+
return JSON.parse(value);
|
|
129
|
+
}
|
|
130
|
+
catch {
|
|
131
|
+
return undefined;
|
|
132
|
+
}
|
|
133
|
+
}
|
|
134
|
+
/**
|
|
135
|
+
* Parses an optional finite numeric header.
|
|
136
|
+
*
|
|
137
|
+
* @param value - Raw header value.
|
|
138
|
+
*/
|
|
139
|
+
function parseFiniteNumber(value) {
|
|
140
|
+
if (value === null)
|
|
141
|
+
return undefined;
|
|
142
|
+
const number = Number(value);
|
|
143
|
+
return Number.isFinite(number) ? number : undefined;
|
|
144
|
+
}
|
|
145
|
+
/**
|
|
146
|
+
* Extracts Krisp's human-readable error string.
|
|
147
|
+
*
|
|
148
|
+
* @param body - Normalized provider error body.
|
|
149
|
+
*/
|
|
150
|
+
function getErrorMessage(body) {
|
|
151
|
+
return isPlainObject(body) && typeof body.error === "string"
|
|
152
|
+
? body.error
|
|
153
|
+
: undefined;
|
|
154
|
+
}
|
|
155
|
+
/**
|
|
156
|
+
* Converts one public camelCase key to Krisp snake_case.
|
|
157
|
+
*
|
|
158
|
+
* @param value - Public key.
|
|
159
|
+
*/
|
|
160
|
+
function toSnakeCase(value) {
|
|
161
|
+
return value.replace(/[A-Z]/g, (letter) => `_${letter.toLowerCase()}`);
|
|
162
|
+
}
|
|
163
|
+
/**
|
|
164
|
+
* Converts one Krisp snake_case key to public camelCase.
|
|
165
|
+
*
|
|
166
|
+
* @param value - Provider key.
|
|
167
|
+
*/
|
|
168
|
+
function toCamelCase(value) {
|
|
169
|
+
return value.replace(/_([a-z0-9])/g, (_, letter) => letter.toUpperCase());
|
|
170
|
+
}
|
|
@@ -0,0 +1,145 @@
|
|
|
1
|
+
import * as z from "zod";
|
|
2
|
+
import type { Encodable } from "@automate.ax/codec";
|
|
3
|
+
/** Krisp profile represented by a personal API key. */
|
|
4
|
+
export declare const KRISP_PROFILE_SCHEMA: z.ZodObject<{
|
|
5
|
+
avatar: z.ZodPrefault<z.ZodNullable<z.ZodURL>>;
|
|
6
|
+
email: z.ZodEmail;
|
|
7
|
+
firstName: z.ZodPrefault<z.ZodNullable<z.ZodString>>;
|
|
8
|
+
id: z.ZodNumber;
|
|
9
|
+
lastName: z.ZodPrefault<z.ZodNullable<z.ZodString>>;
|
|
10
|
+
teamId: z.ZodNumber;
|
|
11
|
+
workspaceId: z.ZodNumber;
|
|
12
|
+
}, z.core.$strip>;
|
|
13
|
+
/** Calendar attendee or diarized speaker attached to a Krisp meeting. */
|
|
14
|
+
export declare const KRISP_PARTICIPANT_SCHEMA: z.ZodObject<{
|
|
15
|
+
email: z.ZodPrefault<z.ZodNullable<z.ZodString>>;
|
|
16
|
+
firstName: z.ZodPrefault<z.ZodNullable<z.ZodString>>;
|
|
17
|
+
lastName: z.ZodPrefault<z.ZodNullable<z.ZodString>>;
|
|
18
|
+
photo: z.ZodPrefault<z.ZodNullable<z.ZodURL>>;
|
|
19
|
+
status: z.ZodPrefault<z.ZodNullable<z.ZodString>>;
|
|
20
|
+
}, z.core.$strip>;
|
|
21
|
+
/** Meeting metadata returned by Krisp list and detail endpoints. */
|
|
22
|
+
export declare const KRISP_MEETING_SCHEMA: z.ZodObject<{
|
|
23
|
+
duration: z.ZodNullable<z.ZodNumber>;
|
|
24
|
+
id: z.ZodString;
|
|
25
|
+
ownership: z.ZodEnum<{
|
|
26
|
+
shared: "shared";
|
|
27
|
+
owned: "owned";
|
|
28
|
+
}>;
|
|
29
|
+
participants: z.ZodOptional<z.ZodArray<z.ZodObject<{
|
|
30
|
+
email: z.ZodPrefault<z.ZodNullable<z.ZodString>>;
|
|
31
|
+
firstName: z.ZodPrefault<z.ZodNullable<z.ZodString>>;
|
|
32
|
+
lastName: z.ZodPrefault<z.ZodNullable<z.ZodString>>;
|
|
33
|
+
photo: z.ZodPrefault<z.ZodNullable<z.ZodURL>>;
|
|
34
|
+
status: z.ZodPrefault<z.ZodNullable<z.ZodString>>;
|
|
35
|
+
}, z.core.$strip>>>;
|
|
36
|
+
source: z.ZodNullable<z.ZodString>;
|
|
37
|
+
startedAt: z.ZodNullable<z.ZodISODateTime>;
|
|
38
|
+
status: z.ZodString;
|
|
39
|
+
tags: z.ZodArray<z.ZodString>;
|
|
40
|
+
title: z.ZodString;
|
|
41
|
+
}, z.core.$strip>;
|
|
42
|
+
/** One diarized transcript segment. Times are seconds from recording start. */
|
|
43
|
+
export declare const KRISP_TRANSCRIPT_SEGMENT_SCHEMA: z.ZodObject<{
|
|
44
|
+
end: z.ZodNumber;
|
|
45
|
+
speaker: z.ZodNumber;
|
|
46
|
+
start: z.ZodNumber;
|
|
47
|
+
text: z.ZodString;
|
|
48
|
+
}, z.core.$strip>;
|
|
49
|
+
declare const KRISP_NOTE_ASSIGNEE_SCHEMA: z.ZodRecord<z.ZodString, z.ZodJSONSchema>;
|
|
50
|
+
export interface KrispNoteBlock {
|
|
51
|
+
[key: string]: Encodable;
|
|
52
|
+
assignee?: z.output<typeof KRISP_NOTE_ASSIGNEE_SCHEMA> | null;
|
|
53
|
+
children?: KrispNoteBlock[];
|
|
54
|
+
completed?: boolean | null;
|
|
55
|
+
dueDate?: string | null;
|
|
56
|
+
text?: string;
|
|
57
|
+
type: string;
|
|
58
|
+
}
|
|
59
|
+
/** Recursive block returned by Krisp's fixed and custom meeting-note sections. */
|
|
60
|
+
export declare const KRISP_NOTE_BLOCK_SCHEMA: z.ZodType<KrispNoteBlock>;
|
|
61
|
+
/** Complete Krisp meeting detail with optional heavy transcript and note data. */
|
|
62
|
+
export declare const KRISP_MEETING_DETAIL_SCHEMA: z.ZodObject<{
|
|
63
|
+
duration: z.ZodNullable<z.ZodNumber>;
|
|
64
|
+
id: z.ZodString;
|
|
65
|
+
ownership: z.ZodEnum<{
|
|
66
|
+
shared: "shared";
|
|
67
|
+
owned: "owned";
|
|
68
|
+
}>;
|
|
69
|
+
participants: z.ZodOptional<z.ZodArray<z.ZodObject<{
|
|
70
|
+
email: z.ZodPrefault<z.ZodNullable<z.ZodString>>;
|
|
71
|
+
firstName: z.ZodPrefault<z.ZodNullable<z.ZodString>>;
|
|
72
|
+
lastName: z.ZodPrefault<z.ZodNullable<z.ZodString>>;
|
|
73
|
+
photo: z.ZodPrefault<z.ZodNullable<z.ZodURL>>;
|
|
74
|
+
status: z.ZodPrefault<z.ZodNullable<z.ZodString>>;
|
|
75
|
+
}, z.core.$strip>>>;
|
|
76
|
+
source: z.ZodNullable<z.ZodString>;
|
|
77
|
+
startedAt: z.ZodNullable<z.ZodISODateTime>;
|
|
78
|
+
status: z.ZodString;
|
|
79
|
+
tags: z.ZodArray<z.ZodString>;
|
|
80
|
+
title: z.ZodString;
|
|
81
|
+
language: z.ZodPrefault<z.ZodNullable<z.ZodString>>;
|
|
82
|
+
meetingType: z.ZodPrefault<z.ZodNullable<z.ZodString>>;
|
|
83
|
+
notes: z.ZodOptional<z.ZodNullable<z.ZodObject<{
|
|
84
|
+
blocks: z.ZodArray<z.ZodType<KrispNoteBlock, unknown, z.core.$ZodTypeInternals<KrispNoteBlock, unknown>>>;
|
|
85
|
+
}, z.core.$strip>>>;
|
|
86
|
+
transcript: z.ZodOptional<z.ZodNullable<z.ZodObject<{
|
|
87
|
+
language: z.ZodPrefault<z.ZodNullable<z.ZodString>>;
|
|
88
|
+
segments: z.ZodPrefault<z.ZodArray<z.ZodObject<{
|
|
89
|
+
end: z.ZodNumber;
|
|
90
|
+
speaker: z.ZodNumber;
|
|
91
|
+
start: z.ZodNumber;
|
|
92
|
+
text: z.ZodString;
|
|
93
|
+
}, z.core.$strip>>>;
|
|
94
|
+
speakers: z.ZodPrefault<z.ZodRecord<z.ZodString, z.ZodObject<{
|
|
95
|
+
email: z.ZodPrefault<z.ZodNullable<z.ZodString>>;
|
|
96
|
+
firstName: z.ZodPrefault<z.ZodNullable<z.ZodString>>;
|
|
97
|
+
lastName: z.ZodPrefault<z.ZodNullable<z.ZodString>>;
|
|
98
|
+
photo: z.ZodPrefault<z.ZodNullable<z.ZodURL>>;
|
|
99
|
+
status: z.ZodPrefault<z.ZodNullable<z.ZodString>>;
|
|
100
|
+
}, z.core.$strip>>>;
|
|
101
|
+
}, z.core.$strip>>>;
|
|
102
|
+
}, z.core.$strip>;
|
|
103
|
+
/** One action item extracted from a Krisp meeting. */
|
|
104
|
+
export declare const KRISP_ACTION_ITEM_SCHEMA: z.ZodObject<{
|
|
105
|
+
assignee: z.ZodPrefault<z.ZodNullable<z.ZodObject<{
|
|
106
|
+
email: z.ZodPrefault<z.ZodNullable<z.ZodString>>;
|
|
107
|
+
firstName: z.ZodPrefault<z.ZodNullable<z.ZodString>>;
|
|
108
|
+
lastName: z.ZodPrefault<z.ZodNullable<z.ZodString>>;
|
|
109
|
+
photo: z.ZodPrefault<z.ZodNullable<z.ZodURL>>;
|
|
110
|
+
status: z.ZodPrefault<z.ZodNullable<z.ZodString>>;
|
|
111
|
+
}, z.core.$strip>>>;
|
|
112
|
+
completed: z.ZodPrefault<z.ZodNullable<z.ZodBoolean>>;
|
|
113
|
+
dueDate: z.ZodPrefault<z.ZodNullable<z.ZodString>>;
|
|
114
|
+
id: z.ZodString;
|
|
115
|
+
meetingId: z.ZodString;
|
|
116
|
+
meetingStartedAt: z.ZodPrefault<z.ZodNullable<z.ZodISODateTime>>;
|
|
117
|
+
meetingTitle: z.ZodString;
|
|
118
|
+
title: z.ZodString;
|
|
119
|
+
}, z.core.$strip>;
|
|
120
|
+
/** Tag used to organize Krisp meetings. */
|
|
121
|
+
export declare const KRISP_TAG_SCHEMA: z.ZodObject<{
|
|
122
|
+
color: z.ZodNullable<z.ZodString>;
|
|
123
|
+
createdAt: z.ZodISODateTime;
|
|
124
|
+
id: z.ZodString;
|
|
125
|
+
name: z.ZodString;
|
|
126
|
+
}, z.core.$strip>;
|
|
127
|
+
/** Recording-import identity returned after Krisp issues an upload URL. */
|
|
128
|
+
export declare const KRISP_IMPORT_SCHEMA: z.ZodObject<{
|
|
129
|
+
expiresAt: z.ZodISODateTime;
|
|
130
|
+
importId: z.ZodString;
|
|
131
|
+
url: z.ZodURL;
|
|
132
|
+
}, z.core.$strip>;
|
|
133
|
+
/** Current processing state for a Krisp recording import. */
|
|
134
|
+
export declare const KRISP_IMPORT_STATUS_SCHEMA: z.ZodObject<{
|
|
135
|
+
error: z.ZodPrefault<z.ZodNullable<z.ZodString>>;
|
|
136
|
+
importId: z.ZodString;
|
|
137
|
+
meetingId: z.ZodPrefault<z.ZodNullable<z.ZodString>>;
|
|
138
|
+
status: z.ZodEnum<{
|
|
139
|
+
failed: "failed";
|
|
140
|
+
ready: "ready";
|
|
141
|
+
uploading: "uploading";
|
|
142
|
+
processing: "processing";
|
|
143
|
+
}>;
|
|
144
|
+
}, z.core.$strip>;
|
|
145
|
+
export {};
|