Files
TalkingQ_Dashboard/scripts/api.js
“yuanmengy” 69785c214f first commit
2026-06-10 17:31:01 +08:00

328 lines
19 KiB
JavaScript

/**
* 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');
}
});