DiffWeave / studio /src /api /client.js
shak3008's picture
feat: complete Truth Register overhaul with RAG playground, Git blame drawer, revision loop, AI hub, de-jargonified lineage graph, and 6 clinical/enterprise starter templates
fe9239d
Raw History Blame Contribute Delete
10.7 kB
/**
* DiffWeave Studio API Client
* Talks directly to the FastAPI bridge, which delegates to DocWeave MCP Server.
* Supports Bearer token authentication and user sessions.
*/
export const CLOUD_BACKEND_URL = 'https://shak3008-diffweave.hf.space';
export function getApiBase() {
if (typeof window !== 'undefined') {
// If running on Vercel or any external static preview, route to HF Space backend
if (window.location.hostname.includes('vercel.app')) {
return `${CLOUD_BACKEND_URL}/api`;
}
}
return '/api';
}
export const API_BASE = getApiBase();
function getHeaders(custom = {}) {
const token = localStorage.getItem('diffweave_token');
const headers = { 'Content-Type': 'application/json', ...custom };
if (token) {
headers['Authorization'] = `Bearer ${token}`;
}
return headers;
}
export const api = {
// -------------------------------------------------------------------------
// Authentication & Session
// -------------------------------------------------------------------------
async signup(username, email, password) {
const res = await fetch(`${API_BASE}/auth/signup`, {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({ username, email, password }),
});
if (!res.ok) throw new Error(await res.text());
const data = await res.json();
if (data.access_token) {
localStorage.setItem('diffweave_token', data.access_token);
localStorage.setItem('diffweave_user', JSON.stringify(data));
}
return data;
},
async login(username, password) {
const res = await fetch(`${API_BASE}/auth/login`, {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({ username, password }),
});
if (!res.ok) throw new Error(await res.text());
const data = await res.json();
if (data.access_token) {
localStorage.setItem('diffweave_token', data.access_token);
localStorage.setItem('diffweave_user', JSON.stringify(data));
}
return data;
},
async demoLogin() {
const res = await fetch(`${API_BASE}/auth/demo-login`, { method: 'POST' });
if (!res.ok) throw new Error(await res.text());
const data = await res.json();
if (data.access_token) {
localStorage.setItem('diffweave_token', data.access_token);
localStorage.setItem('diffweave_user', JSON.stringify(data));
}
return data;
},
setApiKey(token) {
localStorage.setItem('diffweave_token', token);
localStorage.setItem('diffweave_user', JSON.stringify({ email: 'api-key-user', username: 'API Key User' }));
},
logout() {
localStorage.removeItem('diffweave_token');
localStorage.removeItem('diffweave_user');
},
async generateKey(name = 'CLI Personal Access Token', expiresInDays = 90) {
const res = await fetch(`${API_BASE}/auth/generate-key`, {
method: 'POST',
headers: getHeaders(),
body: JSON.stringify({ name, expires_in_days: expiresInDays }),
});
if (!res.ok) throw new Error(await res.text());
return res.json();
},
async syncCLI(token, email, username) {
const res = await fetch(`${API_BASE}/auth/sync-cli`, {
method: 'POST',
headers: getHeaders(),
body: JSON.stringify({ access_token: token, email, username }),
});
if (!res.ok) throw new Error(await res.text());
return res.json();
},
async getWhoami() {
try {
const res = await fetch(`${API_BASE}/auth/whoami`, { headers: getHeaders() });
if (res.ok) return await res.json();
return null;
} catch {
return null;
}
},
getCurrentUser() {
try {
const u = localStorage.getItem('diffweave_user');
return u ? JSON.parse(u) : null;
} catch {
return null;
}
},
// -------------------------------------------------------------------------
// Health & MCP
// -------------------------------------------------------------------------
async getHealth() {
const res = await fetch(`${API_BASE}/health`, { headers: getHeaders() });
return res.json();
},
async getMCPTools() {
const res = await fetch(`${API_BASE}/mcp/tools`, { headers: getHeaders() });
return res.json();
},
// -------------------------------------------------------------------------
// Workspaces
// -------------------------------------------------------------------------
async getWorkspaces() {
const res = await fetch(`${API_BASE}/workspaces`, { headers: getHeaders() });
return res.json();
},
async createWorkspace(name, description = '') {
const res = await fetch(`${API_BASE}/workspaces`, {
method: 'POST',
headers: getHeaders(),
body: JSON.stringify({ name, description }),
});
if (!res.ok) throw new Error(await res.text());
return res.json();
},
async deleteWorkspace(workspaceId) {
const res = await fetch(`${API_BASE}/workspaces/${workspaceId}`, {
method: 'DELETE',
headers: getHeaders(),
});
if (!res.ok) throw new Error(await res.text());
return res.json();
},
async batchDeleteWorkspaces(workspaceIds = [], deleteAll = false) {
const res = await fetch(`${API_BASE}/workspaces/batch-delete`, {
method: 'POST',
headers: getHeaders(),
body: JSON.stringify({ workspace_ids: workspaceIds, delete_all: deleteAll }),
});
if (!res.ok) throw new Error(await res.text());
return res.json();
},
async getWorkspaceStatus(workspaceId) {
const res = await fetch(`${API_BASE}/workspaces/${workspaceId}/status`, { headers: getHeaders() });
return res.json();
},
// -------------------------------------------------------------------------
// Documents
// -------------------------------------------------------------------------
async getDocuments(workspaceId) {
const res = await fetch(`${API_BASE}/workspaces/${workspaceId}/documents`, { headers: getHeaders() });
return res.json();
},
async uploadDocument(workspaceId, file) {
const formData = new FormData();
formData.append('file', file);
const token = localStorage.getItem('diffweave_token');
const headers = {};
if (token) headers['Authorization'] = `Bearer ${token}`;
const res = await fetch(`${API_BASE}/workspaces/${workspaceId}/upload`, {
method: 'POST',
headers,
body: formData,
});
if (!res.ok) throw new Error(await res.text());
return res.json();
},
// -------------------------------------------------------------------------
// Proposals & PRs
// -------------------------------------------------------------------------
async getProposals(workspaceId, status) {
const url = status
? `${API_BASE}/workspaces/${workspaceId}/proposals?status=${status}`
: `${API_BASE}/workspaces/${workspaceId}/proposals`;
const res = await fetch(url, { headers: getHeaders() });
return res.json();
},
async createProposal(workspaceId, payload) {
const res = await fetch(`${API_BASE}/workspaces/${workspaceId}/proposals`, {
method: 'POST',
headers: getHeaders(),
body: JSON.stringify(payload),
});
if (!res.ok) throw new Error(await res.text());
return res.json();
},
async reviewProposal(workspaceId, proposalId, decision, comments = '') {
const res = await fetch(`${API_BASE}/workspaces/${workspaceId}/proposals/${proposalId}/review`, {
method: 'POST',
headers: getHeaders(),
body: JSON.stringify({ decision, comments }),
});
if (!res.ok) throw new Error(await res.text());
return res.json();
},
async batchReview(workspaceId, decision, proposalIds = null, comments = '') {
const res = await fetch(`${API_BASE}/workspaces/${workspaceId}/proposals/batch-review`, {
method: 'POST',
headers: getHeaders(),
body: JSON.stringify({ decision, proposal_ids: proposalIds, comments }),
});
if (!res.ok) throw new Error(await res.text());
return res.json();
},
// -------------------------------------------------------------------------
// Semantic Diff
// -------------------------------------------------------------------------
async getSemanticDiff(workspaceId) {
const res = await fetch(`${API_BASE}/workspaces/${workspaceId}/diff`, { headers: getHeaders() });
return res.json();
},
// -------------------------------------------------------------------------
// Policy Rules
// -------------------------------------------------------------------------
async getRules(workspaceId) {
const res = await fetch(`${API_BASE}/workspaces/${workspaceId}/rules`, { headers: getHeaders() });
return res.json();
},
async createRule(workspaceId, name, operator, configuration) {
const res = await fetch(`${API_BASE}/workspaces/${workspaceId}/rules`, {
method: 'POST',
headers: getHeaders(),
body: JSON.stringify({ name, operator, configuration }),
});
if (!res.ok) throw new Error(await res.text());
return res.json();
},
async deleteRule(ruleId) {
const res = await fetch(`${API_BASE}/rules/${ruleId}`, {
method: 'DELETE',
headers: getHeaders(),
});
return res.json();
},
async validateProposals(workspaceId) {
const res = await fetch(`${API_BASE}/workspaces/${workspaceId}/validate`, { headers: getHeaders() });
return res.json();
},
// -------------------------------------------------------------------------
// Knowledge Register & Graph
// -------------------------------------------------------------------------
async getKnowledgeItems(workspaceId) {
const res = await fetch(`${API_BASE}/workspaces/${workspaceId}/knowledge`, { headers: getHeaders() });
return res.json();
},
async searchKnowledge(workspaceId, query) {
const res = await fetch(
`${API_BASE}/workspaces/${workspaceId}/knowledge/search?q=${encodeURIComponent(query)}`,
{ headers: getHeaders() }
);
return res.json();
},
async getKnowledgeGraph(workspaceId) {
const res = await fetch(`${API_BASE}/workspaces/${workspaceId}/graph`, { headers: getHeaders() });
return res.json();
},
// -------------------------------------------------------------------------
// Audit Trail & Metrics
// -------------------------------------------------------------------------
async getActivityFeed(workspaceId) {
const res = await fetch(`${API_BASE}/workspaces/${workspaceId}/activity`, { headers: getHeaders() });
return res.json();
},
async getWorkflows(workspaceId) {
const res = await fetch(`${API_BASE}/workspaces/${workspaceId}/workflows`, { headers: getHeaders() });
return res.json();
},
};