AgentCare
by Kartha-AI
import axios from "axios";
import { calculateTimeframeDate } from "./Helper.js";
export class FhirClient {
client;
accessToken;
constructor(baseUrl) {
this.client = axios.create({
baseURL: baseUrl,
headers: {
//Authorization: `Bearer ${apiKey}`,
Accept: "application/fhir+json",
Authorization: `Bearer ${this.accessToken}`
},
});
}
setAccessToken(token) {
this.accessToken = token;
this.client.defaults.headers.Authorization = `Bearer ${this.accessToken}`;
}
async search(resourceType, params = {}) {
const searchParams = new URLSearchParams(params);
const response = await this.client.get(`/${resourceType}?${searchParams}`);
return response.data;
}
async get(resourceType, id) {
const response = await this.client.get(`/${resourceType}/${id}`);
return response.data;
}
async executeQuery(queryParams) {
const params = this.buildSearchParams(queryParams);
const response = await this.client.get(`/${queryParams.resourceType}?${params}`);
return this.formatResults(response.data, queryParams.resourceType);
}
async getActiveConditions() {
const response = await this.client.get('/Condition?clinical-status=active');
return this.formatResponse("fhir://Condition/active", response.data);
}
async findPatient(args) {
const params = new URLSearchParams();
if (args.lastName)
params.append('family', args.lastName);
if (args.firstName)
params.append('given', args.firstName);
if (args.birthDate)
params.append('birthdate', args.birthDate);
const response = await this.client.get(`/Patient?${params}`);
// Check if we have results
if (!response.data?.entry?.[0]?.resource) {
return this.formatResponse("fhir://Patient/search", { message: "No patients found" });
}
const resource = response.data.entry[0].resource;
const name = resource.name?.[0] ?? {};
const address = resource.address?.[0] ?? {};
const patient = {
name: name.given?.[0] ?? 'Unknown',
familyName: name.family ?? 'Unknown',
dob: resource.birthDate ?? 'Unknown',
gender: resource.gender ?? 'Unknown',
address: address.line?.[0] ?? 'Unknown',
city: address.city ?? 'Unknown',
state: address.state ?? 'Unknown',
zip: address.postalCode ?? 'Unknown',
id: resource.id ?? 'Unknown'
};
return this.formatResponse("fhir://Patient/search", patient);
}
handleError(error) {
const errorMessage = axios.isAxiosError(error)
? `FHIR API error: ${error.response?.data?.issue?.[0]?.details?.text ?? error.message}`
: error.message;
return { content: [{ type: "text", text: errorMessage }], isError: true };
}
buildSearchParams(queryParams) {
const params = new URLSearchParams();
if (queryParams.codes?.length)
params.append('code', queryParams.codes.join(','));
if (queryParams.dateRange) {
if (queryParams.dateRange.start)
params.append('date', `ge${queryParams.dateRange.start}`);
if (queryParams.dateRange.end)
params.append('date', `le${queryParams.dateRange.end}`);
}
return params;
}
formatResults(data, resourceType) {
return { content: [{ type: "text", text: JSON.stringify(data, null, 2) }] };
}
formatResponse(uri, data) {
return {
content: [{
type: "text",
text: JSON.stringify(data, null, 2)
}]
};
}
async getPatientObservations(args) {
const params = new URLSearchParams();
params.append('patient', `${args.patientId}`);
if (args.code)
params.append('code', args.code);
if (args.status)
params.append('status', args.status);
if (args.dateFrom)
params.append('date', `ge${args.dateFrom}`);
if (args.dateTo)
params.append('date', `le${args.dateTo}`);
const response = await this.client.get(`/Observation?${params}`);
return this.formatResponse(`fhir://Patient/${args.patientId}/observations`, response.data);
}
async getPatientConditions(args) {
const params = new URLSearchParams();
params.append('patient', `${args.patientId}`);
if (args.status)
params.append('clinical-status', args.status);
if (args.onsetDate)
params.append('onset-date', args.onsetDate);
const response = await this.client.get(`/Condition?${params}`);
return this.formatResponse(`fhir://Patient/${args.patientId}/conditions`, response.data);
}
async getPatientMedications(args) {
const params = new URLSearchParams();
params.append('patient', `${args.patientId}`);
if (args.status)
params.append('status', args.status);
const response = await this.client.get(`/MedicationRequest?${params}`);
return this.formatResponse(`fhir://Patient/${args.patientId}/medications`, response.data);
}
async getPatientEncounters(args) {
const params = new URLSearchParams();
params.append('patient', `${args.patientId}`);
if (args.status)
params.append('status', args.status);
if (args.dateFrom)
params.append('date', `ge${args.dateFrom}`);
if (args.dateTo)
params.append('date', `le${args.dateTo}`);
const response = await this.client.get(`/Encounter?${params}`);
return this.formatResponse(`fhir://Patient/${args.patientId}/encounters`, response.data);
}
async getPatientAllergies(args) {
const params = new URLSearchParams();
params.append('patient', args.patientId);
if (args.status)
params.append('clinical-status', args.status);
if (args.type)
params.append('type', args.type);
if (args.category)
params.append('category', args.category);
const response = await this.client.get(`/AllergyIntolerance?${params}`);
return this.formatResponse(`fhir://Patient/${args.patientId}/allergies`, response.data);
}
async getPatientProcedures(args) {
const params = new URLSearchParams();
params.append('patient', `${args.patientId}`);
if (args.status)
params.append('status', args.status);
if (args.dateFrom)
params.append('date', `ge${args.dateFrom}`);
if (args.dateTo)
params.append('date', `le${args.dateTo}`);
const response = await this.client.get(`/Procedure?${params}`);
return this.formatResponse(`fhir://Patient/${args.patientId}/procedures`, response.data);
}
async getPatientCareTeam(args) {
const params = new URLSearchParams();
params.append('patient', `${args.patientId}`);
if (args.status)
params.append('status', args.status);
const response = await this.client.get(`/CareTeam?${params}`);
return this.formatResponse(`fhir://Patient/${args.patientId}/careteam`, response.data);
}
async getPatientCarePlans(args) {
const params = new URLSearchParams();
params.append('patient', `${args.patientId}`);
if (args.status)
params.append('status', args.status);
if (args.category)
params.append('category', args.category);
if (args.dateFrom)
params.append('date', `ge${args.dateFrom}`);
if (args.dateTo)
params.append('date', `le${args.dateTo}`);
const response = await this.client.get(`/CarePlan?${params}`);
return this.formatResponse(`fhir://Patient/${args.patientId}/careplans`, response.data);
}
async getPatientVitalSigns(args) {
const params = new URLSearchParams();
params.append('patient', `${args.patientId}`);
if (args.dateFrom)
params.append('date', `ge${args.dateFrom}`);
if (args.dateTo)
params.append('date', `le${args.dateTo}`);
const response = await this.client.get(`/Observation?${params}`);
return this.formatResponse(`fhir://Patient/${args.patientId}/vital-signs`, response.data);
}
async getMedicationHistory(args) {
const params = new URLSearchParams();
params.append('patient', `${args.patientId}`);
if (args.dateFrom)
params.append('date', `ge${args.dateFrom}`);
if (args.dateTo)
params.append('date', `le${args.dateTo}`);
const response = await this.client.get(`/MedicationStatement?${params}`);
return this.formatResponse(`fhir://Patient/${args.patientId}/medication-history`, response.data);
}
async getPatientLabResults(args) {
const params = new URLSearchParams();
params.append('patient', `${args.patientId}`);
if (args.dateFrom)
params.append('date', `ge${args.dateFrom}`);
if (args.dateTo)
params.append('date', `le${args.dateTo}`);
const response = await this.client.get(`/Observation?${params}`);
return this.formatResponse(`fhir://Patient/${args.patientId}/lab-results`, response.data);
}
async getPatientAppointments(args) {
const params = new URLSearchParams();
params.append('patient', `${args.patientId}`);
if (args.dateFrom)
params.append('date', `ge${args.dateFrom}`);
if (args.dateTo)
params.append('date', `le${args.dateTo}`);
const response = await this.client.get(`/Appointment?${params}`);
return this.formatResponse(`fhir://Patient/${args.patientId}/appointments`, response.data);
}
async getVitalSigns(patientId, timeframe) {
const parms = {
patient: patientId,
category: 'vital-signs',
_sort: '-date',
_count: '50'
};
if (timeframe) {
const date = calculateTimeframeDate(timeframe);
if (date) {
parms["date"] = `ge${date}`;
}
}
return await this.client.get(`/Observation?${parms}`);
}
async getPatientSummaryData(patientId) {
const [patient, conditions, medications, allergies, immunizations, procedures, carePlans, recentLabs, encounters, appointments] = await Promise.all([
this.get("Patient", patientId),
this.search("Condition", { patient: patientId }),
this.search("MedicationRequest", { patient: patientId }),
this.search("AllergyIntolerance", { patient: patientId }),
this.search("Immunization", { patient: patientId }),
this.search("Procedure", { patient: patientId }),
this.search("CarePlan", { patient: patientId }),
this.getPatientLabData(patientId),
this.search("Encounter", { patient: patientId }),
this.search("Appointment", { patient: patientId })
]);
return {
patient,
conditions,
medications,
allergies,
immunizations,
procedures,
carePlans,
recentLabs,
encounters,
appointments
};
}
// Additional helper functions for other prompts
async getPatientConditionData(patientId, timeframe) {
const searchParams = {
patient: patientId,
_sort: "date"
};
if (timeframe) {
const date = calculateTimeframeDate(timeframe);
if (date) {
searchParams["date"] = `ge${date}`;
}
}
return await this.search("Condition", searchParams);
}
async getPatientLabData(patientId, labType) {
const searchParams = {
patient: patientId,
category: "laboratory",
_sort: "-date"
};
if (labType) {
searchParams["code"] = labType;
}
return await this.search("Observation", searchParams);
}
async getPatientCareGapsData(patientId) {
const [patient, immunizations, procedures, carePlans] = await Promise.all([
this.get("Patient", patientId),
this.search("Immunization", { patient: patientId }),
this.search("Procedure", { patient: patientId }),
this.search("CarePlan", { patient: patientId, status: "active" })
]);
return {
patient,
immunizations,
procedures,
carePlans
};
}
getRelevantMetrics(observations, condition) {
// Map conditions to relevant LOINC codes
const metricMap = {
'Diabetes': ['4548-4', '17856-6'], // HbA1c, Glucose
'Hypertension': ['8480-6', '8462-4'], // Systolic BP, Diastolic BP
'Hyperlipidemia': ['2093-3', '2571-8'], // Cholesterol, Triglycerides
};
const conditionName = condition.code?.coding?.[0]?.display || '';
const relevantCodes = metricMap[conditionName] || [];
return observations
.filter((obs) => {
const obsCode = obs.resource.code?.coding?.[0]?.code;
return relevantCodes.includes(obsCode);
})
.map((obs) => {
const value = obs.resource.valueQuantity?.value || 'No value';
const unit = obs.resource.valueQuantity?.unit || '';
const date = obs.resource.effectiveDateTime?.split('T')[0] || 'unknown date';
const name = obs.resource.code?.coding?.[0]?.display || 'Unknown metric';
return `${name}: ${value} ${unit} (${date})`;
});
}
}