121 lines
4.1 KiB
JavaScript
121 lines
4.1 KiB
JavaScript
function authHeaders() {
|
|
return window.getAuthHeaders ? window.getAuthHeaders() : { 'Content-Type': 'application/json' };
|
|
}
|
|
|
|
function parseJsonWithStatus(response) {
|
|
return response.json().catch(function () { return {}; }).then(function(data) {
|
|
data._status = response.status;
|
|
return data;
|
|
});
|
|
}
|
|
|
|
export function fetchAssistantStatus() {
|
|
return fetch('/api/clinical-assistant/status', { headers: authHeaders(), credentials: 'same-origin' })
|
|
.then(function(r) { return r.json(); });
|
|
}
|
|
|
|
export function fetchAssistantExamples() {
|
|
return fetch('/api/clinical-assistant/examples', { headers: authHeaders(), credentials: 'same-origin' })
|
|
.then(function(r) { return r.json(); });
|
|
}
|
|
|
|
export function openAssistantStream(payload, options) {
|
|
options = options || {};
|
|
return fetch('/api/clinical-assistant/chat/stream', {
|
|
method: 'POST',
|
|
headers: authHeaders(),
|
|
credentials: 'same-origin',
|
|
signal: options.signal,
|
|
body: JSON.stringify(payload)
|
|
});
|
|
}
|
|
|
|
export function fetchAssistantChat(payload, options) {
|
|
options = options || {};
|
|
return fetch('/api/clinical-assistant/chat', {
|
|
method: 'POST',
|
|
headers: authHeaders(),
|
|
credentials: 'same-origin',
|
|
signal: options.signal,
|
|
body: JSON.stringify(payload)
|
|
}).then(parseJsonWithStatus);
|
|
}
|
|
|
|
export function requestAssistantHandoff(history) {
|
|
return fetch('/api/clinical-assistant/handoff', {
|
|
method: 'POST', headers: authHeaders(), credentials: 'same-origin',
|
|
body: JSON.stringify({ history: history })
|
|
}).then(parseJsonWithStatus);
|
|
}
|
|
|
|
export function requestAssistantImage(prompt) {
|
|
return fetch('/api/clinical-assistant/image', {
|
|
method: 'POST',
|
|
headers: authHeaders(),
|
|
credentials: 'same-origin',
|
|
body: JSON.stringify({ prompt: prompt })
|
|
}).then(function(r) { return r.json(); });
|
|
}
|
|
|
|
var imageDraft = null;
|
|
export function startAssistantImageJob(prompt, history) {
|
|
const input = { prompt, ...(history === undefined ? {} : { history }) };
|
|
const identity = JSON.stringify(input);
|
|
if (!imageDraft || imageDraft.identity !== identity) imageDraft = { identity, body: { ...input, idempotencyKey: crypto.randomUUID() } };
|
|
return fetch('/api/clinical-assistant/image/jobs', {
|
|
method: 'POST',
|
|
headers: authHeaders(),
|
|
credentials: 'same-origin',
|
|
body: JSON.stringify(imageDraft.body)
|
|
}).then(function(r) { return r.json(); });
|
|
}
|
|
|
|
export function fetchAssistantImageJob(jobId) {
|
|
return fetch('/api/clinical-assistant/image/jobs/' + encodeURIComponent(jobId), {
|
|
headers: authHeaders(),
|
|
credentials: 'same-origin'
|
|
}).then(function(r) { return r.json(); });
|
|
}
|
|
|
|
export function saveAssistantChat(payload) {
|
|
return fetch('/api/clinical-assistant/chats', {
|
|
method: 'POST',
|
|
headers: authHeaders(),
|
|
credentials: 'same-origin',
|
|
body: JSON.stringify(payload)
|
|
}).then(parseJsonWithStatus);
|
|
}
|
|
|
|
export function fetchSavedAssistantChats() {
|
|
return fetch('/api/clinical-assistant/chats', { headers: authHeaders(), credentials: 'same-origin' })
|
|
.then(function(r) { return r.json(); });
|
|
}
|
|
|
|
export function fetchSavedAssistantChat(id) {
|
|
return fetch('/api/clinical-assistant/chats/' + encodeURIComponent(id), { headers: authHeaders(), credentials: 'same-origin' })
|
|
.then(parseJsonWithStatus);
|
|
}
|
|
|
|
export function deleteSavedAssistantChat(id) {
|
|
return fetch('/api/clinical-assistant/chats/' + encodeURIComponent(id), {
|
|
method: 'DELETE',
|
|
headers: authHeaders(),
|
|
credentials: 'same-origin'
|
|
}).then(function(r) { return r.json(); });
|
|
}
|
|
|
|
// Image attachments are input-only: they ride the outgoing clinical question
|
|
// payload and are never persisted or sent with handoff. The server enforces
|
|
// the same limits authoritatively; these mirror them for early feedback.
|
|
export var assistantAttachmentLimits = Object.freeze({
|
|
mimeTypes: ['image/png', 'image/jpeg', 'image/webp'],
|
|
maxImages: 4,
|
|
maxImageBytes: 5 * 1024 * 1024,
|
|
maxTotalBytes: 10 * 1024 * 1024
|
|
});
|
|
|
|
export function assistantAttachmentPayload(attachments) {
|
|
return (Array.isArray(attachments) ? attachments : []).map(function(attachment) {
|
|
return { dataBase64: attachment.dataBase64, mimeType: attachment.mimeType };
|
|
});
|
|
}
|