Files
agentic/frontend/js/store.js
T
2026-06-10 08:20:27 +02:00

186 lines
4.4 KiB
JavaScript

// Store - Application state management
const Store = {
currentDoc: null,
currentSession: null,
documents: [],
sessions: [],
memories: [],
findings: [],
pageChunks: [],
currentPage: 0,
polygonsVisible: true,
textVisible: true,
chunkLabelsVisible: true,
};
// ── API Helper ──
async function api(endpoint, options = {}) {
const defaultOpts = {
headers: { 'Content-Type': 'application/json' },
};
const merged = { ...defaultOpts, ...options };
if (options.body && typeof options.body === 'object' && !(options.body instanceof FormData)) {
merged.body = JSON.stringify(options.body);
}
const url = endpoint.startsWith('http') ? endpoint : `/api${endpoint}`;
const resp = await fetch(url, merged);
if (!resp.ok) {
const text = await resp.text();
throw new Error(`${resp.status}: ${text}`);
}
const ct = resp.headers.get('content-type') || '';
if (ct.includes('json')) return resp.json();
return resp;
}
// ── Document Store ──
const DocStore = {
async load() {
const res = await api('/documents');
Store.documents = res.documents || [];
return Store.documents;
},
async getChunks(docId, page) {
const params = new URLSearchParams();
if (page !== undefined) params.set('page', page);
const res = await api(`/documents/${docId}/chunks?${params}`);
Store.pageChunks = res.chunks || [];
return Store.pageChunks;
},
async upload(file) {
const fd = new FormData();
fd.append('file', file);
const res = await api('/documents/upload', { method: 'POST', body: fd });
return res;
},
async uploadUrl(url, filename) {
const res = await api('/documents/upload', {
method: 'POST',
body: { pdf_url: url, filename },
});
return res;
},
};
// ── Research Store ──
const ResearchStore = {
async run(query, skillNames) {
const res = await api('/research/run', {
method: 'POST',
body: { query, skills: skillNames, doc_id: Store.currentDoc },
});
return res;
},
async createSession(query) {
const res = await api('/research/session', {
method: 'POST',
body: query,
});
return res;
},
async semanticSearch(query, limit = 20) {
const res = await api('/research/semantic', {
method: 'POST',
body: { query, doc_id: Store.currentDoc, limit },
});
return res;
},
async textSearch(query, limit = 20) {
const res = await api('/research/text-search', {
method: 'POST',
body: { query, doc_id: Store.currentDoc, limit },
});
return res;
},
async getFindings(sessionId) {
const res = await api(`/research/findings?session_id=${sessionId || ''}`);
Store.findings = res.findings || [];
return Store.findings;
},
async getMemories(sessionId) {
const res = await api(`/research/memories?session_id=${sessionId || ''}`);
Store.memories = res.memories || [];
return Store.memories;
},
async saveFinding(sessionId, query, response) {
await api('/research/run', {
method: 'POST',
body: { query, doc_id: sessionId },
});
},
};
// ── Memory Store ──
const MemoryStore = {
async save(content, type = 'fact', importance = 3, sourceDocId) {
const res = await api('/memories/save', {
method: 'POST',
body: {
session_id: Store.currentSession,
content,
memory_type: type,
importance,
source_doc_id: sourceDocId,
},
});
return res;
},
async search(query, limit = 10) {
const res = await api('/memories/search', {
method: 'POST',
body: { query, limit },
});
return res;
},
};
// ── Agent Store ──
const AgentStore = {
async getSkills() {
const res = await api('/agents/skills');
return res.skills;
},
async chat(message, model) {
const res = await api('/ollama/chat', {
method: 'POST',
body: {
model: model || 'gpt-oss:20b',
messages: [{ role: 'user', content: message }],
},
});
return res;
},
};
// ── Viewer Store ──
const ViewerStore = {
async getPolygonView(docId, page) {
const res = await api(`/documents/${docId}/polygon-view?page=${page}`);
return res;
},
async getPageText(docId, page) {
const res = await api(`/documents/${docId}/page-text?page=${page}`);
return res;
},
};
// ── Health Store ──
const HealthStore = {
async check() {
const res = await api('/health');
return res;
},
};