/** * TalkingQ Platform - API Interface Layer * All API calls are defined here as stubs. * Replace BASE_URL and implement fetch calls to connect backend. */ const API = { BASE_URL: '/api/v1', // TODO: Replace with actual backend URL // ─── Auth ─────────────────────────────────────────────────────── auth: { login: (credentials) => API._post('/auth/login', credentials), logout: () => API._post('/auth/logout'), me: () => API._get('/auth/me'), getPermissions: () => API._get('/auth/permissions'), refreshToken: () => API._post('/auth/refresh'), }, // ─── Dashboard ────────────────────────────────────────────────── dashboard: { getOverview: (params) => API._get('/dashboard/overview', params), getDAUTrend: (params) => API._get('/dashboard/dau-trend', params), getSessionStats: (params) => API._get('/dashboard/sessions', params), getTurnsPerSession: (params) => API._get('/dashboard/turns', params), getActivationRate: (params) => API._get('/dashboard/activation', params), getRetentionCohort: (params) => API._get('/dashboard/retention', params), getIntentDistribution: (params) => API._get('/dashboard/intents', params), getLanguageStats: (params) => API._get('/dashboard/languages', params), }, // ─── Agent Development ────────────────────────────────────────── agentDev: { // ASR (Automatic Speech Recognition) getASRProviders: () => API._get('/agent-dev/asr/providers'), listASRModels: (params) => API._get('/agent-dev/asr/models', params), createASRModel: (data) => API._post('/agent-dev/asr/models', data), updateASRModel: (id, data) => API._put(`/agent-dev/asr/models/${id}`, data), deleteASRModel: (id) => API._delete(`/agent-dev/asr/models/${id}`), validateASRModel: (id, data = {}) => API._post(`/agent-dev/asr/models/${id}/validate`, data), testASRModel: (id, data = {}) => API._post(`/agent-dev/asr/models/${id}/test`, data), setASRModelEnabled: (id, enabled) => API._put(`/agent-dev/asr/models/${id}/enabled`, { enabled }), getASRConfig: (agentId) => API._get(`/agent-dev/${agentId}/asr`), updateASRConfig: (agentId, config) => API._put(`/agent-dev/${agentId}/asr`, config), testASR: (agentId, audioBlob) => API._post(`/agent-dev/${agentId}/asr/test`, { audio: audioBlob }), getHotwordGroups: (params) => API._get('/agent-dev/asr/hotword-groups', params), createHotwordGroup: (data) => API._post('/agent-dev/asr/hotword-groups', data), updateHotwordGroup: (id, data) => API._put(`/agent-dev/asr/hotword-groups/${id}`, data), deleteHotwordGroup: (id) => API._delete(`/agent-dev/asr/hotword-groups/${id}`), getAgentHotwordGroups: (agentId) => API._get(`/agent-dev/${agentId}/asr/hotword-groups`), bindHotwordGroups: (agentId, groupIds) => API._put(`/agent-dev/${agentId}/asr/hotword-groups`, { groupIds }), // TTS (Text-to-Speech) getTTSProviders: () => API._get('/agent-dev/tts/providers'), listTTSModels: (params) => API._get('/agent-dev/tts/models', params), createTTSModel: (data) => API._post('/agent-dev/tts/models', data), updateTTSModel: (id, data) => API._put(`/agent-dev/tts/models/${id}`, data), deleteTTSModel: (id) => API._delete(`/agent-dev/tts/models/${id}`), validateTTSModel: (id, data = {}) => API._post(`/agent-dev/tts/models/${id}/validate`, data), setTTSModelEnabled: (id, enabled) => API._put(`/agent-dev/tts/models/${id}/enabled`, { enabled }), getTTSConfig: (agentId) => API._get(`/agent-dev/${agentId}/tts`), updateTTSConfig: (agentId, config) => API._put(`/agent-dev/${agentId}/tts`, config), testTTS: (agentId, text) => API._post(`/agent-dev/${agentId}/tts/test`, { text }), previewVoice: (provider, voiceId, text) => API._post('/agent-dev/tts/preview', { provider, voiceId, text }), // Text / LLM models listTextModels: (params) => API._get('/agent-dev/text/models', params), createTextModel: (data) => API._post('/agent-dev/text/models', data), updateTextModel: (id, data) => API._put(`/agent-dev/text/models/${id}`, data), deleteTextModel: (id) => API._delete(`/agent-dev/text/models/${id}`), validateTextModel: (id, data = {}) => API._post(`/agent-dev/text/models/${id}/validate`, data), setTextModelEnabled: (id, enabled) => API._put(`/agent-dev/text/models/${id}/enabled`, { enabled }), getTextConfig: (agentId) => API._get(`/agent-dev/${agentId}/text`), updateTextConfig: (agentId, config) => API._put(`/agent-dev/${agentId}/text`, config), testTextModel: (agentId, prompt) => API._post(`/agent-dev/${agentId}/text/test`, { prompt }), // Runtime variables / state storage listVariables: (agentId, params) => API._get(`/agent-dev/${agentId}/variables`, params), createVariable: (agentId, data) => API._post(`/agent-dev/${agentId}/variables`, data), updateVariable: (agentId, variableId, data) => API._put(`/agent-dev/${agentId}/variables/${variableId}`, data), deleteVariable: (agentId, variableId) => API._delete(`/agent-dev/${agentId}/variables/${variableId}`), injectVariableToPrompt: (agentId, variableId, data = {}) => API._post(`/agent-dev/${agentId}/variables/${variableId}/inject`, data), getVariableState: (agentId, sessionId, params) => API._get(`/agent-dev/${agentId}/sessions/${sessionId}/variables`, params), updateVariableState: (agentId, sessionId, data) => API._put(`/agent-dev/${agentId}/sessions/${sessionId}/variables`, data), // RAG (Retrieval Augmented Generation) getKnowledgeBases: () => API._get('/agent-dev/rag/knowledge-bases'), getAgentRAG: (agentId) => API._get(`/agent-dev/${agentId}/rag`), attachKnowledgeBase: (agentId, kbId) => API._post(`/agent-dev/${agentId}/rag/attach`, { kbId }), detachKnowledgeBase: (agentId, kbId) => API._delete(`/agent-dev/${agentId}/rag/detach/${kbId}`), createKnowledgeBase: (data) => API._post('/agent-dev/rag/knowledge-bases', data), uploadDocument: (kbId, file) => API._upload(`/agent-dev/rag/knowledge-bases/${kbId}/docs`, file), deleteDocument: (kbId, docId) => API._delete(`/agent-dev/rag/knowledge-bases/${kbId}/docs/${docId}`), testRAGQuery: (agentId, query) => API._post(`/agent-dev/${agentId}/rag/test`, { query }), // Language getSupportedLanguages: () => API._get('/agent-dev/languages'), getAgentLanguages: (agentId) => API._get(`/agent-dev/${agentId}/languages`), updateAgentLanguages: (agentId, langs) => API._put(`/agent-dev/${agentId}/languages`, { languages: langs }), setPrimaryLanguage: (agentId, lang) => API._put(`/agent-dev/${agentId}/languages/primary`, { language: lang }), // General agent config saveConfig: (agentId, config) => API._put(`/agent-dev/${agentId}/config`, config), deployAgent: (agentId, data = {}) => API._post(`/agent-dev/${agentId}/deploy`, data), getDeployStatus: (agentId) => API._get(`/agent-dev/${agentId}/deploy/status`), }, // ─── Agent Management ─────────────────────────────────────────── agents: { list: (params) => API._get('/agents', params), get: (id) => API._get(`/agents/${id}`), create: (data) => API._post('/agents', data), update: (id, data) => API._put(`/agents/${id}`, data), delete: (id) => API._post(`/agents/${id}/recycle`, { retentionDays: 7 }), listRecycleBin: (params) => API._get('/agents/recycle-bin', params), restore: (id) => API._post(`/agents/${id}/restore`), purge: (id) => API._delete(`/agents/${id}`), cleanupRecycleBin: () => API._post('/agents/recycle-bin/cleanup'), getVersions: (id) => API._get(`/agents/${id}/versions`), rollback: (id, version) => API._post(`/agents/${id}/rollback`, { version }), }, // ─── Prompt Management ────────────────────────────────────────── prompts: { list: (params) => API._get('/prompts', params), get: (id) => API._get(`/prompts/${id}`), create: (data) => API._post('/prompts', data), update: (id, data) => API._put(`/prompts/${id}`, data), delete: (id) => API._delete(`/prompts/${id}`), publish: (id) => API._post(`/prompts/${id}/publish`), getVersions: (id) => API._get(`/prompts/${id}/versions`), startABTest: (data) => API._post('/prompts/ab-test', data), getABTestResults: (testId) => API._get(`/prompts/ab-test/${testId}/results`), }, // ─── Products ─────────────────────────────────────────────────── products: { list: (params) => API._get('/products', params), get: (id) => API._get(`/products/${id}`), create: (data) => API._post('/products', data), update: (id, data) => API._put(`/products/${id}`, data), delete: (id) => API._delete(`/products/${id}`), }, // ─── Tenant / Company Scope ───────────────────────────────────── tenants: { listCompanies: (params) => API._get('/tenants/companies', params), createCompany: (data) => API._post('/tenants/companies', data), updateCompany: (companyId, data) => API._put(`/tenants/companies/${companyId}`, data), deleteCompany: (companyId) => API._delete(`/tenants/companies/${companyId}`), deleteCompanyWithTransfer: (companyId, data = {}) => API._post(`/tenants/companies/${companyId}/delete`, data), getMyCompany: () => API._get('/tenants/me/company'), getMyScope: () => API._get('/tenants/me/scope'), switchCompany: (companyId) => API._post('/tenants/switch-company', { companyId }), }, // ─── Devices ──────────────────────────────────────────────────── devices: { list: (params) => API._get('/devices', params), get: (id) => API._get(`/devices/${id}`), create: (data) => API._post('/devices', data), batchCreate: (data) => API._post('/devices/batch', data), validateBatch: (data) => API._post('/devices/batch/validate', data), importFile: (file, meta) => API._upload('/devices/import', file, meta), update: (id, data) => API._put(`/devices/${id}`, data), delete: (id) => API._delete(`/devices/${id}`), getHeartbeat: (id) => API._get(`/devices/${id}/heartbeat`), reboot: (id) => API._post(`/devices/${id}/reboot`), getLogs: (id, params) => API._get(`/devices/${id}/logs`, params), bindProduct: (id, productId) => API._post(`/devices/${id}/bind`, { productId }), unbind: (id) => API._post(`/devices/${id}/unbind`), export: (params) => API._get('/devices/export', params), }, // ─── OTA ──────────────────────────────────────────────────────── ota: { list: (params) => API._get('/ota/tasks', params), get: (id) => API._get(`/ota/tasks/${id}`), create: (data) => API._post('/ota/tasks', data), cancel: (id) => API._post(`/ota/tasks/${id}/cancel`), resume: (id) => API._post(`/ota/tasks/${id}/resume`), getProgress: (id) => API._get(`/ota/tasks/${id}/progress`), getFirmwares: (params) => API._get('/ota/firmwares', params), getFirmwaresByProduct: (productId) => API._get('/ota/firmwares', { productId }), uploadFirmware: (file, meta) => API._upload('/ota/firmwares', file, meta), setLatestFirmware: (id, data) => API._post(`/ota/firmwares/${id}/set-latest`, data), setLatestAndCreateTask: (id, data) => API._post(`/ota/firmwares/${id}/set-latest-and-upgrade`, data), deleteFirmware: (id) => API._delete(`/ota/firmwares/${id}`), upgradeSingle: (deviceId, data) => API._post('/ota/single', { device_id: deviceId, ...data }), }, // ─── Sessions ─────────────────────────────────────────────────── sessions: { list: (params) => API._get('/sessions', params), get: (id) => API._get(`/sessions/${id}`), getMessages: (id) => API._get(`/sessions/${id}/messages`), replay: (id) => API._get(`/sessions/${id}/replay`), export: (params) => API._get('/sessions/export', params), getStats: (params) => API._get('/sessions/stats', params), }, // ─── Bad Cases ────────────────────────────────────────────────── badCases: { list: (params) => API._get('/bad-cases', params), get: (id) => API._get(`/bad-cases/${id}`), tag: (id, tags) => API._put(`/bad-cases/${id}/tags`, { tags }), review: (id, data) => API._post(`/bad-cases/${id}/review`, data), close: (id, resolution) => API._post(`/bad-cases/${id}/close`, { resolution }), export: (params) => API._get('/bad-cases/export', params), getStats: (params) => API._get('/bad-cases/stats', params), }, // ─── Notifications ────────────────────────────────────────────── notifications: { // Backend should return tenant/company-scoped notifications only. // Notification item shape: // { // id, eventType, category, severity, title, detail, objectType, // objectId, companyId, companyName, metric, read, createdAt, actionPage // } list: (params) => API._get('/notifications', params), get: (id) => API._get(`/notifications/${id}`), getCatalog: () => API._get('/notifications/catalog'), create: (data) => API._post('/notifications', data), markRead: (id) => API._post(`/notifications/${id}/read`), markAllRead: (params) => API._post('/notifications/read-all', params), archive: (id) => API._post(`/notifications/${id}/archive`), getStats: (params) => API._get('/notifications/stats', params), }, // ─── RBAC ─────────────────────────────────────────────────────── rbac: { getUsers: (params) => API._get('/rbac/users', params), createUser: (data) => API._post('/rbac/users', data), updateUser: (id, data) => API._put(`/rbac/users/${id}`, data), deleteUser: (id) => API._delete(`/rbac/users/${id}`), getRoles: () => API._get('/rbac/roles'), getCurrentPermissions: () => API._get('/rbac/me/permissions'), createRole: (data) => API._post('/rbac/roles', data), updateRole: (id, data) => API._put(`/rbac/roles/${id}`, data), deleteRole: (id) => API._delete(`/rbac/roles/${id}`), getPermissions: () => API._get('/rbac/permissions'), assignRole: (userId, roleId) => API._post('/rbac/users/assign-role', { userId, roleId }), getAuditLogs: (params) => API._get('/rbac/audit-logs', params), }, // ─── Privacy / PII ────────────────────────────────────────────── privacy: { getConfig: () => API._get('/privacy/config'), updateConfig: (data) => API._put('/privacy/config', data), getRules: () => API._get('/privacy/pii-rules'), createRule: (data) => API._post('/privacy/pii-rules', data), updateRule: (id, data) => API._put(`/privacy/pii-rules/${id}`, data), deleteRule: (id) => API._delete(`/privacy/pii-rules/${id}`), getDataRequests: (params) => API._get('/privacy/data-requests', params), processDataRequest: (id, action) => API._post(`/privacy/data-requests/${id}/${action}`), getRetentionPolicies: () => API._get('/privacy/retention-policies'), updateRetentionPolicy: (id, data) => API._put(`/privacy/retention-policies/${id}`, data), }, // ─── Settings ─────────────────────────────────────────────────── settings: { getTenantInfo: () => API._get('/settings/tenant'), updateTenantInfo: (data) => API._put('/settings/tenant', data), getNotifications: () => API._get('/settings/notifications'), // Notification settings shape: // { // rules: { // [eventType]: { enabled, threshold?, thresholdUnit?, channels: ['in_app','email','webhook'] } // } // } updateNotifications: (data) => API._put('/settings/notifications', data), getIntegrations: () => API._get('/settings/integrations'), testWebhook: (url) => API._post('/settings/webhooks/test', { url }), getApiKeys: () => API._get('/settings/api-keys'), createApiKey: (data) => API._post('/settings/api-keys', data), revokeApiKey: (id) => API._delete(`/settings/api-keys/${id}`), }, // ─── Internal helpers ─────────────────────────────────────────── _headers() { const token = localStorage.getItem('tq_token'); return { 'Content-Type': 'application/json', 'Accept': 'application/json', ...(token ? { 'Authorization': `Bearer ${token}` } : {}), }; }, async _request(method, path, body, params) { // TODO: Replace with actual fetch when backend is ready // Simulated delay for demo await new Promise(r => setTimeout(r, 150 + Math.random() * 100)); // Return mock success return { success: true, data: null, message: 'OK (mock)' }; /* Real implementation (uncomment when backend ready): const url = new URL(API.BASE_URL + path, window.location.origin); if (params) Object.entries(params).forEach(([k,v]) => v != null && url.searchParams.set(k, v)); const res = await fetch(url, { method, headers: API._headers(), ...(body ? { body: JSON.stringify(body) } : {}), }); if (!res.ok) throw new Error(`${res.status} ${res.statusText}`); return res.json(); */ }, _get: (path, params) => API._request('GET', path, null, params), _post: (path, body) => API._request('POST', path, body), _put: (path, body) => API._request('PUT', path, body), _delete: (path) => API._request('DELETE', path), async _upload(path, file, meta = {}) { // TODO: Implement multipart upload when backend ready await new Promise(r => setTimeout(r, 300)); return { success: true, data: { fileId: 'mock-file-id', filename: file?.name }, message: 'OK (mock)' }; }, }; // Global error handler window.addEventListener('unhandledrejection', e => { if (e.reason?.message?.includes('401')) { // Redirect to login console.warn('Session expired'); } });