@awell-health/awell-extensions 2.1.73 → 2.1.75
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/extensions/documo/index.d.ts +2 -0
- package/dist/extensions/documo/index.js +20 -0
- package/dist/extensions/documo/index.js.map +1 -0
- package/dist/extensions/documo/settings.d.ts +8 -0
- package/dist/extensions/documo/settings.js +12 -0
- package/dist/extensions/documo/settings.js.map +1 -0
- package/dist/extensions/documo/webhooks/documentFieldValueAssigned.d.ts +33 -0
- package/dist/extensions/documo/webhooks/documentFieldValueAssigned.js +22 -0
- package/dist/extensions/documo/webhooks/documentFieldValueAssigned.js.map +1 -0
- package/dist/extensions/documo/webhooks/index.d.ts +1 -0
- package/dist/extensions/documo/webhooks/index.js +7 -0
- package/dist/extensions/documo/webhooks/index.js.map +1 -0
- package/dist/extensions/documo/webhooks/lib/extractPatientInfoFromOCR/extractPatientInfoFromOCR.d.ts +29 -0
- package/dist/extensions/documo/webhooks/lib/extractPatientInfoFromOCR/extractPatientInfoFromOCR.js +83 -0
- package/dist/extensions/documo/webhooks/lib/extractPatientInfoFromOCR/extractPatientInfoFromOCR.js.map +1 -0
- package/dist/extensions/documo/webhooks/lib/extractPatientInfoFromOCR/index.d.ts +2 -0
- package/dist/extensions/documo/webhooks/lib/extractPatientInfoFromOCR/index.js +9 -0
- package/dist/extensions/documo/webhooks/lib/extractPatientInfoFromOCR/index.js.map +1 -0
- package/dist/extensions/documo/webhooks/lib/extractPatientInfoFromOCR/parser.d.ts +89 -0
- package/dist/extensions/documo/webhooks/lib/extractPatientInfoFromOCR/parser.js +60 -0
- package/dist/extensions/documo/webhooks/lib/extractPatientInfoFromOCR/parser.js.map +1 -0
- package/dist/extensions/documo/webhooks/lib/extractPatientInfoFromOCR/prompt.d.ts +16 -0
- package/dist/extensions/documo/webhooks/lib/extractPatientInfoFromOCR/prompt.js +68 -0
- package/dist/extensions/documo/webhooks/lib/extractPatientInfoFromOCR/prompt.js.map +1 -0
- package/dist/extensions/documo/webhooks/lib/index.d.ts +1 -0
- package/dist/extensions/documo/webhooks/lib/index.js +18 -0
- package/dist/extensions/documo/webhooks/lib/index.js.map +1 -0
- package/dist/extensions/documo/webhooks/ocrDocumentCompleted.d.ts +31 -0
- package/dist/extensions/documo/webhooks/ocrDocumentCompleted.js +59 -0
- package/dist/extensions/documo/webhooks/ocrDocumentCompleted.js.map +1 -0
- package/dist/extensions/index.js +2 -0
- package/dist/extensions/index.js.map +1 -1
- package/dist/extensions/markdown.json +4 -0
- package/dist/extensions/shelly/actions/parseStructuredData/lib/parseStructuredDataWithLLM/parser.d.ts +2 -2
- package/package.json +6 -3
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.Documo = void 0;
|
|
4
|
+
const webhooks_1 = require("./webhooks");
|
|
5
|
+
const settings_1 = require("./settings");
|
|
6
|
+
const extensions_core_1 = require("@awell-health/extensions-core");
|
|
7
|
+
exports.Documo = {
|
|
8
|
+
key: 'documo',
|
|
9
|
+
title: 'Documo',
|
|
10
|
+
description: 'Documo extension for Awell',
|
|
11
|
+
icon_url: 'https://res.cloudinary.com/da7x4rzl4/image/upload/v1766186926/Awell%20Extensions/documo_logo.png',
|
|
12
|
+
category: extensions_core_1.Category.DEMO,
|
|
13
|
+
author: {
|
|
14
|
+
authorType: extensions_core_1.AuthorType.AWELL,
|
|
15
|
+
},
|
|
16
|
+
settings: settings_1.settings,
|
|
17
|
+
actions: {},
|
|
18
|
+
webhooks: webhooks_1.webhooks,
|
|
19
|
+
};
|
|
20
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../../extensions/documo/index.ts"],"names":[],"mappings":";;;AAAA,yCAAqC;AAErC,yCAAqC;AACrC,mEAAoE;AAEvD,QAAA,MAAM,GAAc;IAC/B,GAAG,EAAE,QAAQ;IACb,KAAK,EAAE,QAAQ;IACf,WAAW,EAAE,4BAA4B;IACzC,QAAQ,EACN,kGAAkG;IACpG,QAAQ,EAAE,0BAAQ,CAAC,IAAI;IACvB,MAAM,EAAE;QACN,UAAU,EAAE,4BAAU,CAAC,KAAK;KAC7B;IACD,QAAQ,EAAR,mBAAQ;IACR,OAAO,EAAE,EAAE;IACX,QAAQ,EAAR,mBAAQ;CACT,CAAA"}
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.settings = void 0;
|
|
4
|
+
exports.settings = {
|
|
5
|
+
apiKey: {
|
|
6
|
+
key: 'apiKey',
|
|
7
|
+
label: 'Api Key',
|
|
8
|
+
obfuscated: true,
|
|
9
|
+
description: 'API Key',
|
|
10
|
+
},
|
|
11
|
+
};
|
|
12
|
+
//# sourceMappingURL=settings.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"settings.js","sourceRoot":"","sources":["../../../extensions/documo/settings.ts"],"names":[],"mappings":";;;AAEa,QAAA,QAAQ,GAAG;IACtB,MAAM,EAAE;QACN,GAAG,EAAE,QAAQ;QACb,KAAK,EAAE,SAAS;QAChB,UAAU,EAAE,IAAI;QAChB,WAAW,EAAE,SAAS;KACvB;CACgC,CAAA"}
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
import { type Webhook } from '@awell-health/extensions-core';
|
|
2
|
+
declare const dataPoints: {
|
|
3
|
+
webhookData: {
|
|
4
|
+
key: string;
|
|
5
|
+
valueType: "json";
|
|
6
|
+
};
|
|
7
|
+
};
|
|
8
|
+
interface FieldAssignment {
|
|
9
|
+
field: {
|
|
10
|
+
id: string;
|
|
11
|
+
name: string;
|
|
12
|
+
};
|
|
13
|
+
value: string | null;
|
|
14
|
+
}
|
|
15
|
+
/**
|
|
16
|
+
* Document Field Value Assigned webhook payload
|
|
17
|
+
* Event type: idp.v1.document-field-value.assigned
|
|
18
|
+
* @see https://next.docs.documo.com/
|
|
19
|
+
*/
|
|
20
|
+
export interface DocumentFieldValueAssignedPayload {
|
|
21
|
+
accountId: string;
|
|
22
|
+
workspaceId: string;
|
|
23
|
+
documentId: string;
|
|
24
|
+
status: string;
|
|
25
|
+
user: {
|
|
26
|
+
id: string;
|
|
27
|
+
email: string;
|
|
28
|
+
};
|
|
29
|
+
assignments: FieldAssignment[];
|
|
30
|
+
}
|
|
31
|
+
export declare const documentFieldValueAssigned: Webhook<keyof typeof dataPoints, DocumentFieldValueAssignedPayload>;
|
|
32
|
+
export type DocumentFieldValueAssigned = typeof documentFieldValueAssigned;
|
|
33
|
+
export {};
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.documentFieldValueAssigned = void 0;
|
|
4
|
+
const dataPoints = {
|
|
5
|
+
webhookData: {
|
|
6
|
+
key: 'webhookData',
|
|
7
|
+
valueType: 'json',
|
|
8
|
+
},
|
|
9
|
+
};
|
|
10
|
+
exports.documentFieldValueAssigned = {
|
|
11
|
+
key: 'documentFieldValueAssigned',
|
|
12
|
+
description: 'This webhook is triggered when a field value is assigned to a document.',
|
|
13
|
+
dataPoints,
|
|
14
|
+
onWebhookReceived: async ({ payload }, onSuccess) => {
|
|
15
|
+
await onSuccess({
|
|
16
|
+
data_points: {
|
|
17
|
+
webhookData: JSON.stringify(payload),
|
|
18
|
+
},
|
|
19
|
+
});
|
|
20
|
+
},
|
|
21
|
+
};
|
|
22
|
+
//# sourceMappingURL=documentFieldValueAssigned.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"documentFieldValueAssigned.js","sourceRoot":"","sources":["../../../../extensions/documo/webhooks/documentFieldValueAssigned.ts"],"names":[],"mappings":";;;AAKA,MAAM,UAAU,GAAG;IACjB,WAAW,EAAE;QACX,GAAG,EAAE,aAAa;QAClB,SAAS,EAAE,MAAM;KAClB;CAC4C,CAAA;AA2BlC,QAAA,0BAA0B,GAGnC;IACF,GAAG,EAAE,4BAA4B;IACjC,WAAW,EACT,yEAAyE;IAC3E,UAAU;IACV,iBAAiB,EAAE,KAAK,EAAE,EAAE,OAAO,EAAE,EAAE,SAAS,EAAE,EAAE;QAClD,MAAM,SAAS,CAAC;YACd,WAAW,EAAE;gBACX,WAAW,EAAE,IAAI,CAAC,SAAS,CAAC,OAAO,CAAC;aACrC;SACF,CAAC,CAAA;IACJ,CAAC;CACF,CAAA"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export declare const webhooks: (import("@awell-health/extensions-core").Webhook<"webhookData" | "extractedInfo", import("./ocrDocumentCompleted").OcrDocumentCompletedPayload, Record<string, import("@awell-health/extensions-core").Setting>> | import("@awell-health/extensions-core").Webhook<"webhookData", import("./documentFieldValueAssigned").DocumentFieldValueAssignedPayload, Record<string, import("@awell-health/extensions-core").Setting>>)[];
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.webhooks = void 0;
|
|
4
|
+
const ocrDocumentCompleted_1 = require("./ocrDocumentCompleted");
|
|
5
|
+
const documentFieldValueAssigned_1 = require("./documentFieldValueAssigned");
|
|
6
|
+
exports.webhooks = [ocrDocumentCompleted_1.ocrDocumentCompleted, documentFieldValueAssigned_1.documentFieldValueAssigned];
|
|
7
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../../../extensions/documo/webhooks/index.ts"],"names":[],"mappings":";;;AAAA,iEAA6D;AAC7D,6EAAyE;AAE5D,QAAA,QAAQ,GAAG,CAAC,2CAAoB,EAAE,uDAA0B,CAAC,CAAA"}
|
package/dist/extensions/documo/webhooks/lib/extractPatientInfoFromOCR/extractPatientInfoFromOCR.d.ts
ADDED
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
import { type PatientInfo } from './parser';
|
|
2
|
+
export interface ExtractPatientInfoConfig {
|
|
3
|
+
apiKey: string;
|
|
4
|
+
ocrText: string;
|
|
5
|
+
}
|
|
6
|
+
export interface ExtractedPatientInfo extends PatientInfo {
|
|
7
|
+
/** SHA-256 hash of normalized firstName|lastName|dob for patient matching */
|
|
8
|
+
patient_identifier_hash: string | null;
|
|
9
|
+
}
|
|
10
|
+
/**
|
|
11
|
+
* Generates a deterministic patient identifier hash from first name, last name, and DOB.
|
|
12
|
+
* Returns null if any required field is missing.
|
|
13
|
+
*
|
|
14
|
+
* @param firstName - Patient's first name
|
|
15
|
+
* @param lastName - Patient's last name
|
|
16
|
+
* @param dob - Patient's date of birth (YYYY-MM-DD)
|
|
17
|
+
* @returns SHA-256 hash or null if fields are missing
|
|
18
|
+
*/
|
|
19
|
+
export declare function generatePatientHash(firstName: string | null, lastName: string | null, dob: string | null): string | null;
|
|
20
|
+
/**
|
|
21
|
+
* Extracts patient information from OCR text using an LLM.
|
|
22
|
+
*
|
|
23
|
+
* Uses GPT-4o-mini for cost-effective extraction with good accuracy.
|
|
24
|
+
* Includes retry logic for parsing failures.
|
|
25
|
+
*
|
|
26
|
+
* @param config - Configuration including API key and OCR text
|
|
27
|
+
* @returns Extracted patient information with identifier hash
|
|
28
|
+
*/
|
|
29
|
+
export declare function extractPatientInfoFromOCR(config: ExtractPatientInfoConfig): Promise<ExtractedPatientInfo>;
|
package/dist/extensions/documo/webhooks/lib/extractPatientInfoFromOCR/extractPatientInfoFromOCR.js
ADDED
|
@@ -0,0 +1,83 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.generatePatientHash = generatePatientHash;
|
|
4
|
+
exports.extractPatientInfoFromOCR = extractPatientInfoFromOCR;
|
|
5
|
+
const openai_1 = require("@langchain/openai");
|
|
6
|
+
const crypto_1 = require("crypto");
|
|
7
|
+
const parser_1 = require("./parser");
|
|
8
|
+
const prompt_1 = require("./prompt");
|
|
9
|
+
const MAX_RETRIES = 3;
|
|
10
|
+
/**
|
|
11
|
+
* Generates a deterministic patient identifier hash from first name, last name, and DOB.
|
|
12
|
+
* Returns null if any required field is missing.
|
|
13
|
+
*
|
|
14
|
+
* @param firstName - Patient's first name
|
|
15
|
+
* @param lastName - Patient's last name
|
|
16
|
+
* @param dob - Patient's date of birth (YYYY-MM-DD)
|
|
17
|
+
* @returns SHA-256 hash or null if fields are missing
|
|
18
|
+
*/
|
|
19
|
+
function generatePatientHash(firstName, lastName, dob) {
|
|
20
|
+
if (firstName == null || lastName == null || dob == null) {
|
|
21
|
+
return null;
|
|
22
|
+
}
|
|
23
|
+
// Normalize: lowercase, trim whitespace
|
|
24
|
+
const normalizedFirstName = firstName.toLowerCase().trim();
|
|
25
|
+
const normalizedLastName = lastName.toLowerCase().trim();
|
|
26
|
+
const normalizedDob = dob.trim();
|
|
27
|
+
// Create a deterministic string to hash
|
|
28
|
+
const dataToHash = `${normalizedFirstName}|${normalizedLastName}|${normalizedDob}`;
|
|
29
|
+
// Generate SHA-256 hash
|
|
30
|
+
return (0, crypto_1.createHash)('sha256').update(dataToHash).digest('hex');
|
|
31
|
+
}
|
|
32
|
+
/**
|
|
33
|
+
* Extracts patient information from OCR text using an LLM.
|
|
34
|
+
*
|
|
35
|
+
* Uses GPT-4o-mini for cost-effective extraction with good accuracy.
|
|
36
|
+
* Includes retry logic for parsing failures.
|
|
37
|
+
*
|
|
38
|
+
* @param config - Configuration including API key and OCR text
|
|
39
|
+
* @returns Extracted patient information with identifier hash
|
|
40
|
+
*/
|
|
41
|
+
async function extractPatientInfoFromOCR(config) {
|
|
42
|
+
var _a;
|
|
43
|
+
const { apiKey, ocrText } = config;
|
|
44
|
+
// Initialize the model
|
|
45
|
+
const model = new openai_1.ChatOpenAI({
|
|
46
|
+
modelName: 'gpt-4o-mini-2024-07-18',
|
|
47
|
+
openAIApiKey: apiKey,
|
|
48
|
+
temperature: 0, // Deterministic output for data extraction
|
|
49
|
+
maxRetries: 5,
|
|
50
|
+
timeout: 60000, // 60 second timeout for potentially long documents
|
|
51
|
+
});
|
|
52
|
+
// Format the prompt with the OCR text
|
|
53
|
+
const prompt = await prompt_1.systemPrompt.format({
|
|
54
|
+
ocrText,
|
|
55
|
+
});
|
|
56
|
+
// Create the chain with structured output parsing
|
|
57
|
+
const chain = model.pipe(parser_1.parser);
|
|
58
|
+
// Retry logic for LLM calls
|
|
59
|
+
let result = null;
|
|
60
|
+
let lastError = null;
|
|
61
|
+
for (let attempt = 0; attempt < MAX_RETRIES; attempt++) {
|
|
62
|
+
try {
|
|
63
|
+
result = await chain.invoke(prompt, {
|
|
64
|
+
runName: 'DocumoExtractPatientInfo',
|
|
65
|
+
});
|
|
66
|
+
break; // Success, exit retry loop
|
|
67
|
+
}
|
|
68
|
+
catch (error) {
|
|
69
|
+
lastError = error instanceof Error ? error : new Error(String(error));
|
|
70
|
+
// Continue to next retry
|
|
71
|
+
}
|
|
72
|
+
}
|
|
73
|
+
if (result == null) {
|
|
74
|
+
throw new Error(`Failed to extract patient information after ${MAX_RETRIES} attempts: ${(_a = lastError === null || lastError === void 0 ? void 0 : lastError.message) !== null && _a !== void 0 ? _a : 'Unknown error'}`);
|
|
75
|
+
}
|
|
76
|
+
// Generate the patient identifier hash
|
|
77
|
+
const patient_identifier_hash = generatePatientHash(result.patient_first_name, result.patient_last_name, result.patient_dob);
|
|
78
|
+
return {
|
|
79
|
+
...result,
|
|
80
|
+
patient_identifier_hash,
|
|
81
|
+
};
|
|
82
|
+
}
|
|
83
|
+
//# sourceMappingURL=extractPatientInfoFromOCR.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"extractPatientInfoFromOCR.js","sourceRoot":"","sources":["../../../../../../extensions/documo/webhooks/lib/extractPatientInfoFromOCR/extractPatientInfoFromOCR.ts"],"names":[],"mappings":";;AA0BA,kDAmBC;AAWD,8DAuDC;AA/GD,8CAA8C;AAC9C,mCAAmC;AACnC,qCAAmD;AACnD,qCAAuC;AAEvC,MAAM,WAAW,GAAG,CAAC,CAAA;AAYrB;;;;;;;;GAQG;AACH,SAAgB,mBAAmB,CACjC,SAAwB,EACxB,QAAuB,EACvB,GAAkB;IAElB,IAAI,SAAS,IAAI,IAAI,IAAI,QAAQ,IAAI,IAAI,IAAI,GAAG,IAAI,IAAI,EAAE,CAAC;QACzD,OAAO,IAAI,CAAA;IACb,CAAC;IAED,wCAAwC;IACxC,MAAM,mBAAmB,GAAG,SAAS,CAAC,WAAW,EAAE,CAAC,IAAI,EAAE,CAAA;IAC1D,MAAM,kBAAkB,GAAG,QAAQ,CAAC,WAAW,EAAE,CAAC,IAAI,EAAE,CAAA;IACxD,MAAM,aAAa,GAAG,GAAG,CAAC,IAAI,EAAE,CAAA;IAEhC,wCAAwC;IACxC,MAAM,UAAU,GAAG,GAAG,mBAAmB,IAAI,kBAAkB,IAAI,aAAa,EAAE,CAAA;IAElF,wBAAwB;IACxB,OAAO,IAAA,mBAAU,EAAC,QAAQ,CAAC,CAAC,MAAM,CAAC,UAAU,CAAC,CAAC,MAAM,CAAC,KAAK,CAAC,CAAA;AAC9D,CAAC;AAED;;;;;;;;GAQG;AACI,KAAK,UAAU,yBAAyB,CAC7C,MAAgC;;IAEhC,MAAM,EAAE,MAAM,EAAE,OAAO,EAAE,GAAG,MAAM,CAAA;IAElC,uBAAuB;IACvB,MAAM,KAAK,GAAG,IAAI,mBAAU,CAAC;QAC3B,SAAS,EAAE,wBAAwB;QACnC,YAAY,EAAE,MAAM;QACpB,WAAW,EAAE,CAAC,EAAE,2CAA2C;QAC3D,UAAU,EAAE,CAAC;QACb,OAAO,EAAE,KAAK,EAAE,mDAAmD;KACpE,CAAC,CAAA;IAEF,sCAAsC;IACtC,MAAM,MAAM,GAAG,MAAM,qBAAY,CAAC,MAAM,CAAC;QACvC,OAAO;KACR,CAAC,CAAA;IAEF,kDAAkD;IAClD,MAAM,KAAK,GAAG,KAAK,CAAC,IAAI,CAAC,eAAM,CAAC,CAAA;IAEhC,4BAA4B;IAC5B,IAAI,MAAM,GAAuB,IAAI,CAAA;IACrC,IAAI,SAAS,GAAiB,IAAI,CAAA;IAElC,KAAK,IAAI,OAAO,GAAG,CAAC,EAAE,OAAO,GAAG,WAAW,EAAE,OAAO,EAAE,EAAE,CAAC;QACvD,IAAI,CAAC;YACH,MAAM,GAAG,MAAM,KAAK,CAAC,MAAM,CAAC,MAAM,EAAE;gBAClC,OAAO,EAAE,0BAA0B;aACpC,CAAC,CAAA;YACF,MAAK,CAAC,2BAA2B;QACnC,CAAC;QAAC,OAAO,KAAK,EAAE,CAAC;YACf,SAAS,GAAG,KAAK,YAAY,KAAK,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,IAAI,KAAK,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC,CAAA;YACrE,yBAAyB;QAC3B,CAAC;IACH,CAAC;IAED,IAAI,MAAM,IAAI,IAAI,EAAE,CAAC;QACnB,MAAM,IAAI,KAAK,CACb,+CAA+C,WAAW,cAAc,MAAA,SAAS,aAAT,SAAS,uBAAT,SAAS,CAAE,OAAO,mCAAI,eAAe,EAAE,CAChH,CAAA;IACH,CAAC;IAED,uCAAuC;IACvC,MAAM,uBAAuB,GAAG,mBAAmB,CACjD,MAAM,CAAC,kBAAkB,EACzB,MAAM,CAAC,iBAAiB,EACxB,MAAM,CAAC,WAAW,CACnB,CAAA;IAED,OAAO;QACL,GAAG,MAAM;QACT,uBAAuB;KACxB,CAAA;AACH,CAAC"}
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.PatientInfoSchema = exports.generatePatientHash = exports.extractPatientInfoFromOCR = void 0;
|
|
4
|
+
var extractPatientInfoFromOCR_1 = require("./extractPatientInfoFromOCR");
|
|
5
|
+
Object.defineProperty(exports, "extractPatientInfoFromOCR", { enumerable: true, get: function () { return extractPatientInfoFromOCR_1.extractPatientInfoFromOCR; } });
|
|
6
|
+
Object.defineProperty(exports, "generatePatientHash", { enumerable: true, get: function () { return extractPatientInfoFromOCR_1.generatePatientHash; } });
|
|
7
|
+
var parser_1 = require("./parser");
|
|
8
|
+
Object.defineProperty(exports, "PatientInfoSchema", { enumerable: true, get: function () { return parser_1.PatientInfoSchema; } });
|
|
9
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../../../../../extensions/documo/webhooks/lib/extractPatientInfoFromOCR/index.ts"],"names":[],"mappings":";;;AAAA,yEAKoC;AAJlC,sIAAA,yBAAyB,OAAA;AACzB,gIAAA,mBAAmB,OAAA;AAIrB,mCAA8D;AAArD,2GAAA,iBAAiB,OAAA"}
|
|
@@ -0,0 +1,89 @@
|
|
|
1
|
+
import { StructuredOutputParser } from 'langchain/output_parsers';
|
|
2
|
+
import { z } from 'zod';
|
|
3
|
+
/**
|
|
4
|
+
* Zod schema for the extracted patient information
|
|
5
|
+
*/
|
|
6
|
+
export declare const PatientInfoSchema: z.ZodObject<{
|
|
7
|
+
patient_first_name: z.ZodNullable<z.ZodString>;
|
|
8
|
+
patient_last_name: z.ZodNullable<z.ZodString>;
|
|
9
|
+
patient_full_name: z.ZodNullable<z.ZodString>;
|
|
10
|
+
patient_dob: z.ZodNullable<z.ZodString>;
|
|
11
|
+
patient_phone: z.ZodNullable<z.ZodString>;
|
|
12
|
+
insurance_name: z.ZodNullable<z.ZodString>;
|
|
13
|
+
insurance_policy_number: z.ZodNullable<z.ZodString>;
|
|
14
|
+
insurance_group_number: z.ZodNullable<z.ZodString>;
|
|
15
|
+
insurance_policy_holder: z.ZodNullable<z.ZodString>;
|
|
16
|
+
referring_physician_name: z.ZodNullable<z.ZodString>;
|
|
17
|
+
confidence_level: z.ZodNumber;
|
|
18
|
+
extraction_notes: z.ZodString;
|
|
19
|
+
}, "strip", z.ZodTypeAny, {
|
|
20
|
+
patient_first_name: string | null;
|
|
21
|
+
patient_last_name: string | null;
|
|
22
|
+
patient_full_name: string | null;
|
|
23
|
+
patient_dob: string | null;
|
|
24
|
+
patient_phone: string | null;
|
|
25
|
+
insurance_name: string | null;
|
|
26
|
+
insurance_policy_number: string | null;
|
|
27
|
+
insurance_group_number: string | null;
|
|
28
|
+
insurance_policy_holder: string | null;
|
|
29
|
+
referring_physician_name: string | null;
|
|
30
|
+
confidence_level: number;
|
|
31
|
+
extraction_notes: string;
|
|
32
|
+
}, {
|
|
33
|
+
patient_first_name: string | null;
|
|
34
|
+
patient_last_name: string | null;
|
|
35
|
+
patient_full_name: string | null;
|
|
36
|
+
patient_dob: string | null;
|
|
37
|
+
patient_phone: string | null;
|
|
38
|
+
insurance_name: string | null;
|
|
39
|
+
insurance_policy_number: string | null;
|
|
40
|
+
insurance_group_number: string | null;
|
|
41
|
+
insurance_policy_holder: string | null;
|
|
42
|
+
referring_physician_name: string | null;
|
|
43
|
+
confidence_level: number;
|
|
44
|
+
extraction_notes: string;
|
|
45
|
+
}>;
|
|
46
|
+
export type PatientInfo = z.infer<typeof PatientInfoSchema>;
|
|
47
|
+
/**
|
|
48
|
+
* Structured Output Parser for patient information extraction
|
|
49
|
+
*/
|
|
50
|
+
export declare const parser: StructuredOutputParser<z.ZodObject<{
|
|
51
|
+
patient_first_name: z.ZodNullable<z.ZodString>;
|
|
52
|
+
patient_last_name: z.ZodNullable<z.ZodString>;
|
|
53
|
+
patient_full_name: z.ZodNullable<z.ZodString>;
|
|
54
|
+
patient_dob: z.ZodNullable<z.ZodString>;
|
|
55
|
+
patient_phone: z.ZodNullable<z.ZodString>;
|
|
56
|
+
insurance_name: z.ZodNullable<z.ZodString>;
|
|
57
|
+
insurance_policy_number: z.ZodNullable<z.ZodString>;
|
|
58
|
+
insurance_group_number: z.ZodNullable<z.ZodString>;
|
|
59
|
+
insurance_policy_holder: z.ZodNullable<z.ZodString>;
|
|
60
|
+
referring_physician_name: z.ZodNullable<z.ZodString>;
|
|
61
|
+
confidence_level: z.ZodNumber;
|
|
62
|
+
extraction_notes: z.ZodString;
|
|
63
|
+
}, "strip", z.ZodTypeAny, {
|
|
64
|
+
patient_first_name: string | null;
|
|
65
|
+
patient_last_name: string | null;
|
|
66
|
+
patient_full_name: string | null;
|
|
67
|
+
patient_dob: string | null;
|
|
68
|
+
patient_phone: string | null;
|
|
69
|
+
insurance_name: string | null;
|
|
70
|
+
insurance_policy_number: string | null;
|
|
71
|
+
insurance_group_number: string | null;
|
|
72
|
+
insurance_policy_holder: string | null;
|
|
73
|
+
referring_physician_name: string | null;
|
|
74
|
+
confidence_level: number;
|
|
75
|
+
extraction_notes: string;
|
|
76
|
+
}, {
|
|
77
|
+
patient_first_name: string | null;
|
|
78
|
+
patient_last_name: string | null;
|
|
79
|
+
patient_full_name: string | null;
|
|
80
|
+
patient_dob: string | null;
|
|
81
|
+
patient_phone: string | null;
|
|
82
|
+
insurance_name: string | null;
|
|
83
|
+
insurance_policy_number: string | null;
|
|
84
|
+
insurance_group_number: string | null;
|
|
85
|
+
insurance_policy_holder: string | null;
|
|
86
|
+
referring_physician_name: string | null;
|
|
87
|
+
confidence_level: number;
|
|
88
|
+
extraction_notes: string;
|
|
89
|
+
}>>;
|
|
@@ -0,0 +1,60 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.parser = exports.PatientInfoSchema = void 0;
|
|
4
|
+
const output_parsers_1 = require("langchain/output_parsers");
|
|
5
|
+
const zod_1 = require("zod");
|
|
6
|
+
/**
|
|
7
|
+
* Zod schema for the extracted patient information
|
|
8
|
+
*/
|
|
9
|
+
exports.PatientInfoSchema = zod_1.z.object({
|
|
10
|
+
patient_first_name: zod_1.z
|
|
11
|
+
.string()
|
|
12
|
+
.nullable()
|
|
13
|
+
.describe("Patient's first/given name"),
|
|
14
|
+
patient_last_name: zod_1.z
|
|
15
|
+
.string()
|
|
16
|
+
.nullable()
|
|
17
|
+
.describe("Patient's last/family name"),
|
|
18
|
+
patient_full_name: zod_1.z
|
|
19
|
+
.string()
|
|
20
|
+
.nullable()
|
|
21
|
+
.describe('Full name as written in document'),
|
|
22
|
+
patient_dob: zod_1.z
|
|
23
|
+
.string()
|
|
24
|
+
.nullable()
|
|
25
|
+
.describe('Date of birth in YYYY-MM-DD format'),
|
|
26
|
+
patient_phone: zod_1.z
|
|
27
|
+
.string()
|
|
28
|
+
.nullable()
|
|
29
|
+
.describe("Patient's phone number in E.164 format (e.g. +14155551234)"),
|
|
30
|
+
insurance_name: zod_1.z
|
|
31
|
+
.string()
|
|
32
|
+
.nullable()
|
|
33
|
+
.describe('Insurance company or plan name'),
|
|
34
|
+
insurance_policy_number: zod_1.z
|
|
35
|
+
.string()
|
|
36
|
+
.nullable()
|
|
37
|
+
.describe('Policy/Member ID number'),
|
|
38
|
+
insurance_group_number: zod_1.z
|
|
39
|
+
.string()
|
|
40
|
+
.nullable()
|
|
41
|
+
.describe('Group number if present'),
|
|
42
|
+
insurance_policy_holder: zod_1.z.string().nullable().describe('Policy holder name'),
|
|
43
|
+
referring_physician_name: zod_1.z
|
|
44
|
+
.string()
|
|
45
|
+
.nullable()
|
|
46
|
+
.describe('Name of referring physician/provider'),
|
|
47
|
+
confidence_level: zod_1.z
|
|
48
|
+
.number()
|
|
49
|
+
.min(0)
|
|
50
|
+
.max(100)
|
|
51
|
+
.describe('Confidence level of the extraction (0-100)'),
|
|
52
|
+
extraction_notes: zod_1.z
|
|
53
|
+
.string()
|
|
54
|
+
.describe('Brief notes about the extraction process'),
|
|
55
|
+
});
|
|
56
|
+
/**
|
|
57
|
+
* Structured Output Parser for patient information extraction
|
|
58
|
+
*/
|
|
59
|
+
exports.parser = output_parsers_1.StructuredOutputParser.fromZodSchema(exports.PatientInfoSchema);
|
|
60
|
+
//# sourceMappingURL=parser.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"parser.js","sourceRoot":"","sources":["../../../../../../extensions/documo/webhooks/lib/extractPatientInfoFromOCR/parser.ts"],"names":[],"mappings":";;;AAAA,6DAAiE;AACjE,6BAAuB;AAEvB;;GAEG;AACU,QAAA,iBAAiB,GAAG,OAAC,CAAC,MAAM,CAAC;IACxC,kBAAkB,EAAE,OAAC;SAClB,MAAM,EAAE;SACR,QAAQ,EAAE;SACV,QAAQ,CAAC,4BAA4B,CAAC;IACzC,iBAAiB,EAAE,OAAC;SACjB,MAAM,EAAE;SACR,QAAQ,EAAE;SACV,QAAQ,CAAC,4BAA4B,CAAC;IACzC,iBAAiB,EAAE,OAAC;SACjB,MAAM,EAAE;SACR,QAAQ,EAAE;SACV,QAAQ,CAAC,kCAAkC,CAAC;IAC/C,WAAW,EAAE,OAAC;SACX,MAAM,EAAE;SACR,QAAQ,EAAE;SACV,QAAQ,CAAC,oCAAoC,CAAC;IACjD,aAAa,EAAE,OAAC;SACb,MAAM,EAAE;SACR,QAAQ,EAAE;SACV,QAAQ,CAAC,4DAA4D,CAAC;IACzE,cAAc,EAAE,OAAC;SACd,MAAM,EAAE;SACR,QAAQ,EAAE;SACV,QAAQ,CAAC,gCAAgC,CAAC;IAC7C,uBAAuB,EAAE,OAAC;SACvB,MAAM,EAAE;SACR,QAAQ,EAAE;SACV,QAAQ,CAAC,yBAAyB,CAAC;IACtC,sBAAsB,EAAE,OAAC;SACtB,MAAM,EAAE;SACR,QAAQ,EAAE;SACV,QAAQ,CAAC,yBAAyB,CAAC;IACtC,uBAAuB,EAAE,OAAC,CAAC,MAAM,EAAE,CAAC,QAAQ,EAAE,CAAC,QAAQ,CAAC,oBAAoB,CAAC;IAC7E,wBAAwB,EAAE,OAAC;SACxB,MAAM,EAAE;SACR,QAAQ,EAAE;SACV,QAAQ,CAAC,sCAAsC,CAAC;IACnD,gBAAgB,EAAE,OAAC;SAChB,MAAM,EAAE;SACR,GAAG,CAAC,CAAC,CAAC;SACN,GAAG,CAAC,GAAG,CAAC;SACR,QAAQ,CAAC,4CAA4C,CAAC;IACzD,gBAAgB,EAAE,OAAC;SAChB,MAAM,EAAE;SACR,QAAQ,CAAC,0CAA0C,CAAC;CACxD,CAAC,CAAA;AAIF;;GAEG;AACU,QAAA,MAAM,GAAG,uCAAsB,CAAC,aAAa,CAAC,yBAAiB,CAAC,CAAA"}
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
import { ChatPromptTemplate } from '@langchain/core/prompts';
|
|
2
|
+
/**
|
|
3
|
+
* System Prompt Template for extracting patient information from OCR text
|
|
4
|
+
*
|
|
5
|
+
* The OCR text typically comes from faxed medical documents such as:
|
|
6
|
+
* - Referral forms
|
|
7
|
+
* - Lab results
|
|
8
|
+
* - Insurance cards
|
|
9
|
+
* - New patient intake forms
|
|
10
|
+
*
|
|
11
|
+
* The prompt instructs the LLM to carefully extract:
|
|
12
|
+
* - Patient demographic information
|
|
13
|
+
* - Insurance details
|
|
14
|
+
* - Referring physician information
|
|
15
|
+
*/
|
|
16
|
+
export declare const systemPrompt: ChatPromptTemplate<import("@langchain/core/prompts").ParamsFromFString<"\nYou are an expert medical document analyst specializing in extracting patient information from OCR-processed faxed documents.\n\nYour task is to carefully analyze the provided OCR text and extract structured patient information. This text may come from various medical documents including referral forms, insurance cards, lab results, or intake forms.\n\nIMPORTANT EXTRACTION RULES:\n1. Extract ONLY information that is explicitly present in the document.\n2. Be careful to distinguish between different phone numbers:\n - The patient's phone number (mobile preferred, then home)\n - Fax numbers (DO NOT use these as patient phone)\n - Office/clinic phone numbers (DO NOT use these as patient phone)\n3. For phone numbers, format in E.164 format assuming US country code (+1).\n - Example: (415) 555-1234 → +14155551234\n - Example: 415-555-1234 → +14155551234\n - Only include digits after the +1 prefix (no spaces, dashes, or parentheses)\n4. For date of birth, convert to YYYY-MM-DD format if possible.\n5. For insurance information, extract:\n - Insurance company/plan name\n - Policy/Member ID number\n - Group number (if present)\n - Policy holder name (if different from patient)\n6. For referring physician, extract their full name as shown.\n7. If information cannot be found, use null for that field.\n8. Do not guess or infer information that is not clearly stated.\n\nCONFIDENCE GUIDELINES:\n- 90-100: All fields clearly found with unambiguous values\n- 70-89: Most important fields found, some minor ambiguity\n- 50-69: Key fields found but with moderate uncertainty\n- 30-49: Limited information extracted, significant uncertainty\n- 0-29: Very little information could be reliably extracted\n\nRespond exclusively with a valid JSON object containing these keys:\n- patient_first_name: string | null (patient's first/given name)\n- patient_last_name: string | null (patient's last/family name)\n- patient_full_name: string | null (full name as written in document)\n- patient_dob: string | null (date of birth in YYYY-MM-DD format)\n- patient_phone: string | null (patient's phone in E.164 format e.g. +14155551234, prefer mobile, NEVER use fax numbers)\n- insurance_name: string | null (insurance company or plan name)\n- insurance_policy_number: string | null (policy/member ID)\n- insurance_group_number: string | null (group number if present)\n- insurance_policy_holder: string | null (policy holder name if different from patient)\n- referring_physician_name: string | null (name of referring physician/provider)\n- confidence_level: number (0-100 indicating extraction reliability)\n- extraction_notes: string (brief notes about the extraction, any challenges or ambiguities)\n\nOCR Text from Document:\n{ocrText}\n">, any>;
|
|
@@ -0,0 +1,68 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.systemPrompt = void 0;
|
|
4
|
+
const prompts_1 = require("@langchain/core/prompts");
|
|
5
|
+
/**
|
|
6
|
+
* System Prompt Template for extracting patient information from OCR text
|
|
7
|
+
*
|
|
8
|
+
* The OCR text typically comes from faxed medical documents such as:
|
|
9
|
+
* - Referral forms
|
|
10
|
+
* - Lab results
|
|
11
|
+
* - Insurance cards
|
|
12
|
+
* - New patient intake forms
|
|
13
|
+
*
|
|
14
|
+
* The prompt instructs the LLM to carefully extract:
|
|
15
|
+
* - Patient demographic information
|
|
16
|
+
* - Insurance details
|
|
17
|
+
* - Referring physician information
|
|
18
|
+
*/
|
|
19
|
+
exports.systemPrompt = prompts_1.ChatPromptTemplate.fromTemplate(`
|
|
20
|
+
You are an expert medical document analyst specializing in extracting patient information from OCR-processed faxed documents.
|
|
21
|
+
|
|
22
|
+
Your task is to carefully analyze the provided OCR text and extract structured patient information. This text may come from various medical documents including referral forms, insurance cards, lab results, or intake forms.
|
|
23
|
+
|
|
24
|
+
IMPORTANT EXTRACTION RULES:
|
|
25
|
+
1. Extract ONLY information that is explicitly present in the document.
|
|
26
|
+
2. Be careful to distinguish between different phone numbers:
|
|
27
|
+
- The patient's phone number (mobile preferred, then home)
|
|
28
|
+
- Fax numbers (DO NOT use these as patient phone)
|
|
29
|
+
- Office/clinic phone numbers (DO NOT use these as patient phone)
|
|
30
|
+
3. For phone numbers, format in E.164 format assuming US country code (+1).
|
|
31
|
+
- Example: (415) 555-1234 → +14155551234
|
|
32
|
+
- Example: 415-555-1234 → +14155551234
|
|
33
|
+
- Only include digits after the +1 prefix (no spaces, dashes, or parentheses)
|
|
34
|
+
4. For date of birth, convert to YYYY-MM-DD format if possible.
|
|
35
|
+
5. For insurance information, extract:
|
|
36
|
+
- Insurance company/plan name
|
|
37
|
+
- Policy/Member ID number
|
|
38
|
+
- Group number (if present)
|
|
39
|
+
- Policy holder name (if different from patient)
|
|
40
|
+
6. For referring physician, extract their full name as shown.
|
|
41
|
+
7. If information cannot be found, use null for that field.
|
|
42
|
+
8. Do not guess or infer information that is not clearly stated.
|
|
43
|
+
|
|
44
|
+
CONFIDENCE GUIDELINES:
|
|
45
|
+
- 90-100: All fields clearly found with unambiguous values
|
|
46
|
+
- 70-89: Most important fields found, some minor ambiguity
|
|
47
|
+
- 50-69: Key fields found but with moderate uncertainty
|
|
48
|
+
- 30-49: Limited information extracted, significant uncertainty
|
|
49
|
+
- 0-29: Very little information could be reliably extracted
|
|
50
|
+
|
|
51
|
+
Respond exclusively with a valid JSON object containing these keys:
|
|
52
|
+
- patient_first_name: string | null (patient's first/given name)
|
|
53
|
+
- patient_last_name: string | null (patient's last/family name)
|
|
54
|
+
- patient_full_name: string | null (full name as written in document)
|
|
55
|
+
- patient_dob: string | null (date of birth in YYYY-MM-DD format)
|
|
56
|
+
- patient_phone: string | null (patient's phone in E.164 format e.g. +14155551234, prefer mobile, NEVER use fax numbers)
|
|
57
|
+
- insurance_name: string | null (insurance company or plan name)
|
|
58
|
+
- insurance_policy_number: string | null (policy/member ID)
|
|
59
|
+
- insurance_group_number: string | null (group number if present)
|
|
60
|
+
- insurance_policy_holder: string | null (policy holder name if different from patient)
|
|
61
|
+
- referring_physician_name: string | null (name of referring physician/provider)
|
|
62
|
+
- confidence_level: number (0-100 indicating extraction reliability)
|
|
63
|
+
- extraction_notes: string (brief notes about the extraction, any challenges or ambiguities)
|
|
64
|
+
|
|
65
|
+
OCR Text from Document:
|
|
66
|
+
{ocrText}
|
|
67
|
+
`);
|
|
68
|
+
//# sourceMappingURL=prompt.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"prompt.js","sourceRoot":"","sources":["../../../../../../extensions/documo/webhooks/lib/extractPatientInfoFromOCR/prompt.ts"],"names":[],"mappings":";;;AAAA,qDAA4D;AAE5D;;;;;;;;;;;;;GAaG;AACU,QAAA,YAAY,GAAG,4BAAkB,CAAC,YAAY,CAAC;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;CAgD3D,CAAC,CAAA"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export * from './extractPatientInfoFromOCR';
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
|
3
|
+
if (k2 === undefined) k2 = k;
|
|
4
|
+
var desc = Object.getOwnPropertyDescriptor(m, k);
|
|
5
|
+
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
|
6
|
+
desc = { enumerable: true, get: function() { return m[k]; } };
|
|
7
|
+
}
|
|
8
|
+
Object.defineProperty(o, k2, desc);
|
|
9
|
+
}) : (function(o, m, k, k2) {
|
|
10
|
+
if (k2 === undefined) k2 = k;
|
|
11
|
+
o[k2] = m[k];
|
|
12
|
+
}));
|
|
13
|
+
var __exportStar = (this && this.__exportStar) || function(m, exports) {
|
|
14
|
+
for (var p in m) if (p !== "default" && !Object.prototype.hasOwnProperty.call(exports, p)) __createBinding(exports, m, p);
|
|
15
|
+
};
|
|
16
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
17
|
+
__exportStar(require("./extractPatientInfoFromOCR"), exports);
|
|
18
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../../../../extensions/documo/webhooks/lib/index.ts"],"names":[],"mappings":";;;;;;;;;;;;;;;;AAAA,8DAA2C"}
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
import { type Webhook } from '@awell-health/extensions-core';
|
|
2
|
+
declare const dataPoints: {
|
|
3
|
+
webhookData: {
|
|
4
|
+
key: string;
|
|
5
|
+
valueType: "json";
|
|
6
|
+
};
|
|
7
|
+
extractedInfo: {
|
|
8
|
+
key: string;
|
|
9
|
+
valueType: "json";
|
|
10
|
+
};
|
|
11
|
+
};
|
|
12
|
+
/**
|
|
13
|
+
* OCR Document Completed webhook payload
|
|
14
|
+
* Event type: ocr.v1.document.complete
|
|
15
|
+
* @see https://next.docs.documo.com/
|
|
16
|
+
*/
|
|
17
|
+
export interface OcrDocumentCompletedPayload {
|
|
18
|
+
id: string;
|
|
19
|
+
accountId: string;
|
|
20
|
+
wsDocId: string;
|
|
21
|
+
status: string;
|
|
22
|
+
pagesCount: number;
|
|
23
|
+
createdAt: string;
|
|
24
|
+
completedAt: string;
|
|
25
|
+
ocrData?: {
|
|
26
|
+
text: string;
|
|
27
|
+
};
|
|
28
|
+
}
|
|
29
|
+
export declare const ocrDocumentCompleted: Webhook<keyof typeof dataPoints, OcrDocumentCompletedPayload>;
|
|
30
|
+
export type OcrDocumentCompleted = typeof ocrDocumentCompleted;
|
|
31
|
+
export {};
|
|
@@ -0,0 +1,59 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.ocrDocumentCompleted = void 0;
|
|
4
|
+
const lib_1 = require("./lib");
|
|
5
|
+
const dataPoints = {
|
|
6
|
+
webhookData: {
|
|
7
|
+
key: 'webhookData',
|
|
8
|
+
valueType: 'json',
|
|
9
|
+
},
|
|
10
|
+
extractedInfo: {
|
|
11
|
+
key: 'extractedInfo',
|
|
12
|
+
valueType: 'json',
|
|
13
|
+
},
|
|
14
|
+
};
|
|
15
|
+
exports.ocrDocumentCompleted = {
|
|
16
|
+
key: 'ocrDocumentCompleted',
|
|
17
|
+
dataPoints,
|
|
18
|
+
onEvent: async ({ payload: { payload }, onSuccess, onError, helpers: { getOpenAIConfig }, }) => {
|
|
19
|
+
var _a, _b;
|
|
20
|
+
const ocrText = (_b = (_a = payload.ocrData) === null || _a === void 0 ? void 0 : _a.text) !== null && _b !== void 0 ? _b : '';
|
|
21
|
+
// Get OpenAI API key from configuration
|
|
22
|
+
const { apiKey } = getOpenAIConfig();
|
|
23
|
+
// Extract patient information from OCR text using LLM
|
|
24
|
+
let extractedInfo;
|
|
25
|
+
try {
|
|
26
|
+
extractedInfo = await (0, lib_1.extractPatientInfoFromOCR)({
|
|
27
|
+
apiKey,
|
|
28
|
+
ocrText,
|
|
29
|
+
});
|
|
30
|
+
}
|
|
31
|
+
catch (error) {
|
|
32
|
+
await onError({
|
|
33
|
+
response: {
|
|
34
|
+
statusCode: 500,
|
|
35
|
+
message: error instanceof Error
|
|
36
|
+
? error.message
|
|
37
|
+
: 'Failed to extract patient information from OCR text',
|
|
38
|
+
},
|
|
39
|
+
});
|
|
40
|
+
return;
|
|
41
|
+
}
|
|
42
|
+
await onSuccess({
|
|
43
|
+
data_points: {
|
|
44
|
+
webhookData: JSON.stringify(payload),
|
|
45
|
+
extractedInfo: JSON.stringify(extractedInfo),
|
|
46
|
+
},
|
|
47
|
+
// Use the patient hash as the patient identifier for matching
|
|
48
|
+
...(extractedInfo.patient_identifier_hash != null
|
|
49
|
+
? {
|
|
50
|
+
patient_identifier: {
|
|
51
|
+
system: 'documo-ocr-hash',
|
|
52
|
+
value: extractedInfo.patient_identifier_hash,
|
|
53
|
+
},
|
|
54
|
+
}
|
|
55
|
+
: {}),
|
|
56
|
+
});
|
|
57
|
+
},
|
|
58
|
+
};
|
|
59
|
+
//# sourceMappingURL=ocrDocumentCompleted.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"ocrDocumentCompleted.js","sourceRoot":"","sources":["../../../../extensions/documo/webhooks/ocrDocumentCompleted.ts"],"names":[],"mappings":";;;AAIA,+BAAiD;AAEjD,MAAM,UAAU,GAAG;IACjB,WAAW,EAAE;QACX,GAAG,EAAE,aAAa;QAClB,SAAS,EAAE,MAAM;KAClB;IACD,aAAa,EAAE;QACb,GAAG,EAAE,eAAe;QACpB,SAAS,EAAE,MAAM;KAClB;CAC4C,CAAA;AAoBlC,QAAA,oBAAoB,GAG7B;IACF,GAAG,EAAE,sBAAsB;IAC3B,UAAU;IACV,OAAO,EAAE,KAAK,EAAE,EACd,OAAO,EAAE,EAAE,OAAO,EAAE,EACpB,SAAS,EACT,OAAO,EACP,OAAO,EAAE,EAAE,eAAe,EAAE,GAC7B,EAAE,EAAE;;QACH,MAAM,OAAO,GAAG,MAAA,MAAA,OAAO,CAAC,OAAO,0CAAE,IAAI,mCAAI,EAAE,CAAA;QAE3C,wCAAwC;QACxC,MAAM,EAAE,MAAM,EAAE,GAAG,eAAe,EAAE,CAAA;QAEpC,sDAAsD;QACtD,IAAI,aAAa,CAAA;QACjB,IAAI,CAAC;YACH,aAAa,GAAG,MAAM,IAAA,+BAAyB,EAAC;gBAC9C,MAAM;gBACN,OAAO;aACR,CAAC,CAAA;QACJ,CAAC;QAAC,OAAO,KAAK,EAAE,CAAC;YACf,MAAM,OAAO,CAAC;gBACZ,QAAQ,EAAE;oBACR,UAAU,EAAE,GAAG;oBACf,OAAO,EACL,KAAK,YAAY,KAAK;wBACpB,CAAC,CAAC,KAAK,CAAC,OAAO;wBACf,CAAC,CAAC,qDAAqD;iBAC5D;aACF,CAAC,CAAA;YACF,OAAM;QACR,CAAC;QAED,MAAM,SAAS,CAAC;YACd,WAAW,EAAE;gBACX,WAAW,EAAE,IAAI,CAAC,SAAS,CAAC,OAAO,CAAC;gBACpC,aAAa,EAAE,IAAI,CAAC,SAAS,CAAC,aAAa,CAAC;aAC7C;YACD,8DAA8D;YAC9D,GAAG,CAAC,aAAa,CAAC,uBAAuB,IAAI,IAAI;gBAC/C,CAAC,CAAC;oBACE,kBAAkB,EAAE;wBAClB,MAAM,EAAE,iBAAiB;wBACzB,KAAK,EAAE,aAAa,CAAC,uBAAuB;qBAC7C;iBACF;gBACH,CAAC,CAAC,EAAE,CAAC;SACR,CAAC,CAAA;IACJ,CAAC;CACF,CAAA"}
|
package/dist/extensions/index.js
CHANGED
|
@@ -51,6 +51,7 @@ const collectData_1 = require("./collectData");
|
|
|
51
51
|
const customerIo_1 = require("./customerIo");
|
|
52
52
|
const dateHelpers_1 = require("./dateHelpers");
|
|
53
53
|
const dockHealth_1 = require("./dockHealth");
|
|
54
|
+
const documo_1 = require("./documo");
|
|
54
55
|
const docuSign_1 = require("./docuSign");
|
|
55
56
|
const dropboxSign_1 = require("./dropboxSign");
|
|
56
57
|
const elation_1 = require("./elation");
|
|
@@ -114,6 +115,7 @@ exports.extensions = [
|
|
|
114
115
|
dateHelpers_1.dateHelpers,
|
|
115
116
|
dockHealth_1.dockHealth,
|
|
116
117
|
docuSign_1.DocuSign,
|
|
118
|
+
documo_1.Documo,
|
|
117
119
|
dropboxSign_1.DropboxSign,
|
|
118
120
|
elation_1.Elation,
|
|
119
121
|
epic_1.epic,
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../extensions/index.ts"],"names":[],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAAA,iDAA6C;AAC7C,yCAAqC;AACrC,qCAAiC;AACjC,mCAA+B;AAC/B,6CAAyC;AACzC,mCAA+B;AAC/B,mCAA+B;AAC/B,2CAAuC;AACvC,yCAAqC;AACrC,mDAA+C;AAC/C,qCAAiC;AACjC,6CAAyC;AACzC,yCAAqC;AACrC,+CAA2C;AAC3C,6CAAyC;AACzC,+CAA2C;AAC3C,6CAAyC;AACzC,yCAAqC;AACrC,+CAA2C;AAC3C,uCAAmC;AACnC,iCAA6B;AAC7B,iDAA6C;AAC7C,uDAAkD;AAClD,yCAAqC;AACrC,2CAAuC;AACvC,6CAAyC;AACzC,2CAAuC;AACvC,yCAAqC;AACrC,+CAA0C;AAC1C,uCAAmC;AACnC,iEAA6D;AAC7D,uCAAmC;AACnC,yCAAqC;AACrC,2CAAuC;AACvC,2CAAuC;AACvC,uCAAmC;AACnC,iCAAsC;AACtC,uCAAmC;AACnC,+CAA2C;AAC3C,0CAA0C;AAC1C,+CAA2C;AAC3C,iCAA6B;AAC7B,yCAAqC;AACrC,6DAA+C;AAC/C,iCAA6B;AAC7B,qCAAiC;AACjC,mCAA+B;AAC/B,qCAAiC;AACjC,yCAAqC;AACrC,yCAAqC;AACrC,+CAAyC;AACzC,2CAAuC;AACvC,qCAAiC;AACjC,uCAAmC;AACnC,yCAAqC;AACrC,+CAA2C;AAC3C,uCAAmC;AACnC,iCAA6B;AAC7B,mCAA+B;AAE/B,sDAAuC;AAG1B,QAAA,QAAQ,GAAa,IAAI,CAAA;AAEzB,QAAA,UAAU,GAAG;IACxB,aAAK;IACL,aAAK;IACL,2BAAY;IACZ,mBAAQ;IACR,eAAM;IACN,aAAK;IACL,uBAAU;IACV,qBAAS;IACT,mBAAQ;IACR,6BAAa;IACb,eAAM;IACN,uBAAU;IACV,mBAAQ;IACR,yBAAW;IACX,uBAAU;IACV,yBAAW;IACX,uBAAU;IACV,mBAAQ;IACR,yBAAW;IACX,iBAAO;IACP,WAAI;IACJ,2BAAY;IACZ,gCAAc;IACd,mBAAQ;IACR,qBAAS;IACT,uBAAU;IACV,qBAAS;IACT,mBAAQ;IACR,wBAAU;IACV,iBAAO;IACP,2CAAoB;IACpB,iBAAO;IACP,mBAAQ;IACR,qBAAS;IACT,qBAAS;IACT,iBAAO;IACP,oBAAa;IACb,yBAAW;IACX,iBAAO;IACP,aAAa;IACb,yBAAW;IACX,WAAI;IACJ,mBAAQ;IACR,6BAAQ;IACR,WAAI;IACJ,eAAM;IACN,aAAK;IACL,eAAM;IACN,mBAAQ;IACR,mBAAQ;IACR,uBAAS;IACT,qBAAS;IACT,eAAM;IACN,iBAAO;IACP,mBAAQ;IACR,yBAAW;IACX,iBAAO;IACP,WAAI;IACJ,aAAK;CACN,CAAA"}
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../extensions/index.ts"],"names":[],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAAA,iDAA6C;AAC7C,yCAAqC;AACrC,qCAAiC;AACjC,mCAA+B;AAC/B,6CAAyC;AACzC,mCAA+B;AAC/B,mCAA+B;AAC/B,2CAAuC;AACvC,yCAAqC;AACrC,mDAA+C;AAC/C,qCAAiC;AACjC,6CAAyC;AACzC,yCAAqC;AACrC,+CAA2C;AAC3C,6CAAyC;AACzC,+CAA2C;AAC3C,6CAAyC;AACzC,qCAAiC;AACjC,yCAAqC;AACrC,+CAA2C;AAC3C,uCAAmC;AACnC,iCAA6B;AAC7B,iDAA6C;AAC7C,uDAAkD;AAClD,yCAAqC;AACrC,2CAAuC;AACvC,6CAAyC;AACzC,2CAAuC;AACvC,yCAAqC;AACrC,+CAA0C;AAC1C,uCAAmC;AACnC,iEAA6D;AAC7D,uCAAmC;AACnC,yCAAqC;AACrC,2CAAuC;AACvC,2CAAuC;AACvC,uCAAmC;AACnC,iCAAsC;AACtC,uCAAmC;AACnC,+CAA2C;AAC3C,0CAA0C;AAC1C,+CAA2C;AAC3C,iCAA6B;AAC7B,yCAAqC;AACrC,6DAA+C;AAC/C,iCAA6B;AAC7B,qCAAiC;AACjC,mCAA+B;AAC/B,qCAAiC;AACjC,yCAAqC;AACrC,yCAAqC;AACrC,+CAAyC;AACzC,2CAAuC;AACvC,qCAAiC;AACjC,uCAAmC;AACnC,yCAAqC;AACrC,+CAA2C;AAC3C,uCAAmC;AACnC,iCAA6B;AAC7B,mCAA+B;AAE/B,sDAAuC;AAG1B,QAAA,QAAQ,GAAa,IAAI,CAAA;AAEzB,QAAA,UAAU,GAAG;IACxB,aAAK;IACL,aAAK;IACL,2BAAY;IACZ,mBAAQ;IACR,eAAM;IACN,aAAK;IACL,uBAAU;IACV,qBAAS;IACT,mBAAQ;IACR,6BAAa;IACb,eAAM;IACN,uBAAU;IACV,mBAAQ;IACR,yBAAW;IACX,uBAAU;IACV,yBAAW;IACX,uBAAU;IACV,mBAAQ;IACR,eAAM;IACN,yBAAW;IACX,iBAAO;IACP,WAAI;IACJ,2BAAY;IACZ,gCAAc;IACd,mBAAQ;IACR,qBAAS;IACT,uBAAU;IACV,qBAAS;IACT,mBAAQ;IACR,wBAAU;IACV,iBAAO;IACP,2CAAoB;IACpB,iBAAO;IACP,mBAAQ;IACR,qBAAS;IACT,qBAAS;IACT,iBAAO;IACP,oBAAa;IACb,yBAAW;IACX,iBAAO;IACP,aAAa;IACb,yBAAW;IACX,WAAI;IACJ,mBAAQ;IACR,6BAAQ;IACR,WAAI;IACJ,eAAM;IACN,aAAK;IACL,eAAM;IACN,mBAAQ;IACR,mBAAQ;IACR,uBAAS;IACT,qBAAS;IACT,eAAM;IACN,iBAAO;IACP,mBAAQ;IACR,yBAAW;IACX,iBAAO;IACP,WAAI;IACJ,aAAK;CACN,CAAA"}
|
|
@@ -71,6 +71,10 @@
|
|
|
71
71
|
"readme": "---\ntitle: DocuSign\ndescription: Make your business faster, simpler and more cost-efficient with electronic agreements. Agree with confidence, with intuitive signing experiences across virtually any device.\n---\n# DocuSign\n\nMake your business faster, simpler and more cost-efficient with electronic agreements. Agree with confidence, with intuitive signing experiences across virtually any device.\n\n## Extension settings\n\nIn order to set up this extension, you will need to provide the following settings:\n\n1. **Integration key (client ID)** - An integration key identifies your integration and links to its configuration values. This can be obtained in your developer account from the **Apps and Keys** page\n2. **API Account ID** - A GUID value that identifies your account. This can be obtained in your developer account from the **Apps and Keys** page\n3. **Impersonated User ID (UserID)** - This is a GUID identifying the DocuSign user that you will be impersonating with the access token. Your own User ID can be found at the top of the **Apps and Keys** page.\n4. **RSA private key (in Base64 format)** - This is for the integration key you obtained above and can also be created on the **Apps and Keys** page (DocuSign also allows uploading your own keys). You only need the private key, and it can only be copied once. Make sure to retain it for your records. Provide it in Base64 format - if you copy the key as is, it will not be valid as newlines and formatting won't be persisted.\n5. **Base API URL** - Base API URL for API calls matching your environment on DocuSign. Defaults to: https://demo.docusign.net. Can be obtained from **Account Base URI** section of the **Apps and Keys** page or the `base_uri` property in the response of a call to the `/oauth/userinfo`.\n 1. `DEV` environment: https://demo.docusign.net (default)\n 2. `PRODUCTION` environment: **https://`{server}`.docusign.net**, where `{server}` is the data center location of your production account (for example, **CA**, **NA2**, or **EU**)\n6. **Return URL template** - Return URL for your application to which DocuSign will redirect the user after signing the document. Set when you self host your application. You can use {sessionId}, {pathwayId}, {activityId} and {stakeholderId} variables to construct the URL, where variables will be replaced with actual values. Defaults to: \"https://goto.development.awell.health/?sessionId={sessionId}\". Remember that this URL MUST match the one you registered for your app in DocuSign settings. [See docs](https://developers.docusign.com/platform/configure-app/#redirect-uri) for more details.\n\nAlso, before working with **DocuSign** you should receive consent of the user to impersonate them with the API calls (even for your own account). Check the details on how to do that [on DocuSign docs](https://developers.docusign.com/platform/auth/consent/obtaining-individual-consent/). It's a ONE TIME operation and is required for API calls to work for specific client-scope-uri combination. Required params explained below:\n\n- `YOUR_REQUESTED_SCOPES`: This extension uses JWT Grant, so in place of `YOUR_REQUESTED_SCOPES` you MUST put at least `signature%20impersonation`.\n - sample consent URL: https://account-d.docusign.com/oauth/auth?response_type=code&scope=signature%20impersonation%20click.manage%20click.send&client_id=XYZ-123&redirect_uri=https://test.com\n\n## Custom Actions\n\n### Embedded signing\n\nEmbedded Signing gives users the ability to sign documents directly from Awell Hosted Pages using DocuSign's embedded signing feature. First an embedded signature request with a template is created and then a signing URL is generated for the signature request. Via the signing URL, we can let the user sign the request from within Awell.\n\nEmbedded signing behaves as a blocking action where the action is only completed when the signature request is effectively signed.\n\n**In order to add embedded signing, you need to add 2 actions to you care flow:**\n\n1. First, add the \"Create embedded signature request with template\" action. This action will create an embedded signature request based on a template and return a **sign URL**.\n2. Second, add the \"Embedded signing\" action. In this action you will have to configure the **sign URL** you got from the first action.\n\n**Please note that the signing URL generated in the first step is only valid for 5 minutes and is one-time only.** This means that from as soon as the first action is activated, the user has 5 minutes to complete the signing request. Loading a session by the user also means that sign url is loaded and refreshing the page will cause the link to expire. When the sign URL has expired, the document cannot be signed anymore and and the process would have to be repeated.\n",
|
|
72
72
|
"changelog": "# DocuSign changelog\n"
|
|
73
73
|
},
|
|
74
|
+
"documo": {
|
|
75
|
+
"readme": "---\ntitle: Documo\ndescription: Documo extension for Awell\n---\n# Documo extension\n\nDocumo extension for Awell\n\n## Actions\n\n- **Hello World**: A simple action that logs a message.\n\n## Webhooks\n\n- **Hello World Webhook**: A simple webhook that receives events.\n\n## Settings\n\n- **Api Key**: API Key\n",
|
|
76
|
+
"changelog": "# Documo changelog\n\n## [Unreleased]\n\n- Initial release\n"
|
|
77
|
+
},
|
|
74
78
|
"dropboxSign": {
|
|
75
79
|
"readme": "---\ntitle: Dropbox Sign\ndescription: Dropbox Sign (formerly HelloSign) is the easiest way to send, receive and manage legally binding electronic signatures.\n---\n# Dropbox Sign\n\nDropbox Sign (formerly HelloSign) is the easiest way to send, receive and manage legally binding electronic signatures.\n\n## Extension settings\n\nIn order to set up this extension, you will need to provide the following settings:\n\n1. API Key\n2. Client ID - the id of the API app created in Dropbox Sign. Only required if want to use embedded signature requests.\n3. Test mode - whether you want to execute all API calls to DropboxSign in test mode. When test mode is enabled, signature requests will not be legally binding. When disabled, keep in mind that you must upgrade to a paid DropboxSign API plan to create signature requests via the extension.\n\n## Custom Actions\n\n### Embedded signing\n\nEmbedded Signing gives users the ability to sign documents directly from Awell Hosted Pages using Dropbox Sign's embedded signing feature. First an embedded signature request with a template is created and then a signing URL is generated for the signature request. Via the signing URL, we can let the user sign the request from within Awell.\n\nEmbedded signing behaves as a blocking action where the action is only completed when the signature request is effectively signed.\n\n**In order to add embedded signing, you need to add 2 actions to you care flow:**\n\n1. First, add the \"Create embedded signature request with template\" action. This action will create an embedded signature request based on a template and return a **sign URL**.\n2. Second, add the \"Embedded signing\" action. In this action you will have to configure the **sign URL** you got from the first action.\n\n**Please note that the signing URL generated in the first step is only valid for 1 hour.** This means that from as soon as the first action is activated, the user has 1 hour to complete the signing request. When the sign URL has expired, the document cannot be signed anymore and and the process would have to be repeated.\n\n### Send signature request with template\n\nCreates and sends a new SignatureRequest based off of a template specified with the template id parameter. The request will be send to specified signer via email. Please note that is a non-blocking action and that the care flow will automatically continue once the request is sent. It won't wait for the actual signing of the request.\n\nTo send signature requests via the DropboxSign API you must upgrade to a [paid API plan](https://app.hellosign.com/api/pricing).\n\n### Get signature request\n\nReturns the SignatureRequest specified by the signature request id parameter.\n\n### Send request reminder\n\nSends an email to the signer reminding them to sign the signature request. You cannot send a reminder within 1 hour of the last reminder that was sent. This includes manual AND automatic reminders.\n\n**Important:**\n\n- The email address specified to send the reminder to needs to be an email address of an actual signer linked to the signature request. If not, the action will fail.\n- This action can not be used with embedded signature requests.\n\n### Cancel signature request\n\nCancels an incomplete signature request. This action is not reversible.\n",
|
|
76
80
|
"changelog": "# Dropbox Sign changelog"
|
|
@@ -14,11 +14,11 @@ export declare const parser: StructuredOutputParser<z.ZodObject<{
|
|
|
14
14
|
confidence_level: z.ZodNumber;
|
|
15
15
|
extraction_explanation: z.ZodString;
|
|
16
16
|
}, "strip", z.ZodTypeAny, {
|
|
17
|
-
extracted_data: Record<string, any>;
|
|
18
17
|
confidence_level: number;
|
|
18
|
+
extracted_data: Record<string, any>;
|
|
19
19
|
extraction_explanation: string;
|
|
20
20
|
}, {
|
|
21
|
-
extracted_data: Record<string, any>;
|
|
22
21
|
confidence_level: number;
|
|
22
|
+
extracted_data: Record<string, any>;
|
|
23
23
|
extraction_explanation: string;
|
|
24
24
|
}>>;
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@awell-health/awell-extensions",
|
|
3
|
-
"version": "2.1.
|
|
3
|
+
"version": "2.1.75",
|
|
4
4
|
"packageManager": "yarn@4.5.3",
|
|
5
5
|
"main": "dist/src/index.js",
|
|
6
6
|
"repository": {
|
|
@@ -22,7 +22,8 @@
|
|
|
22
22
|
"test-local": "jest --verbose",
|
|
23
23
|
"prepack": "yarn build",
|
|
24
24
|
"test-server": "ts-node-dev --respawn --transpile-only ./src/test-server.ts",
|
|
25
|
-
"prepare": "husky"
|
|
25
|
+
"prepare": "husky",
|
|
26
|
+
"generate-extension": "ts-node ./scripts/generate-extension.ts"
|
|
26
27
|
},
|
|
27
28
|
"types": "dist/src/index.d.ts",
|
|
28
29
|
"exports": {
|
|
@@ -73,6 +74,7 @@
|
|
|
73
74
|
"@types/showdown": "^2.0.0",
|
|
74
75
|
"@types/uuid": "^10.0.0",
|
|
75
76
|
"@types/xml2js": "^0.4.12",
|
|
77
|
+
"@types/yargs": "^17.0.32",
|
|
76
78
|
"@typescript-eslint/eslint-plugin": "^5.52.0",
|
|
77
79
|
"@yarnpkg/sdks": "^3.2.0",
|
|
78
80
|
"algoliasearch": "^5.24.0",
|
|
@@ -95,7 +97,8 @@
|
|
|
95
97
|
"ts-jest": "29.2.5",
|
|
96
98
|
"ts-node": "^10.9.2",
|
|
97
99
|
"ts-node-dev": "^2.0.0",
|
|
98
|
-
"typescript": "5.7.2"
|
|
100
|
+
"typescript": "5.7.2",
|
|
101
|
+
"yargs": "^17.7.2"
|
|
99
102
|
},
|
|
100
103
|
"dependencies": {
|
|
101
104
|
"@airtop/sdk": "^0.1.44",
|