Changeset 0.37.14 (#226)
Co-authored-by: gobha <jasafpro@gmail.com> Co-committed-by: gobha <jasafpro@gmail.com>
This commit is contained in:
@@ -73,6 +73,7 @@ export function createDomains(restClient) {
|
||||
complete: (data, signal) => rc.stream('/api/v1/chat/completions', data, signal),
|
||||
regenerate: (id, msgId, data, signal) => rc.stream(`/api/v1/channels/${id}/messages/${msgId}/regenerate`, data, signal),
|
||||
editMessage: (id, msgId, content) => rc.post(`/api/v1/channels/${id}/messages/${msgId}/edit`, { content }),
|
||||
deleteMessage: (id, msgId) => rc.del(`/api/v1/channels/${id}/messages/${msgId}`),
|
||||
siblings: (id, msgId) => rc.get(`/api/v1/channels/${id}/messages/${msgId}/siblings`),
|
||||
path: (id) => rc.get(`/api/v1/channels/${id}/path`),
|
||||
cursor: (id, leafId) => rc.put(`/api/v1/channels/${id}/cursor`, { active_leaf_id: leafId }),
|
||||
@@ -184,11 +185,13 @@ export function createDomains(restClient) {
|
||||
|
||||
// ── 11. Notifications ──────────────────
|
||||
notifications: {
|
||||
list: (opts) => rc.get('/api/v1/notifications' + _qs(opts)),
|
||||
markRead: (id) => rc.post(`/api/v1/notifications/${id}/read`, {}),
|
||||
prefs: () => rc.get('/api/v1/notifications/preferences'),
|
||||
setPref: (type, data) => rc.put(`/api/v1/notifications/preferences/${encodeURIComponent(type)}`, data),
|
||||
delPref: (type) => rc.del(`/api/v1/notifications/preferences/${encodeURIComponent(type)}`),
|
||||
list: (opts) => rc.get('/api/v1/notifications' + _qs(opts)),
|
||||
unreadCount: () => rc.get('/api/v1/notifications/unread-count'),
|
||||
markRead: (id) => rc.post(`/api/v1/notifications/${id}/read`, {}),
|
||||
markAllRead: () => rc.post('/api/v1/notifications/mark-all-read', {}),
|
||||
prefs: () => rc.get('/api/v1/notifications/preferences'),
|
||||
setPref: (type, data) => rc.put(`/api/v1/notifications/preferences/${encodeURIComponent(type)}`, data),
|
||||
delPref: (type) => rc.del(`/api/v1/notifications/preferences/${encodeURIComponent(type)}`),
|
||||
},
|
||||
|
||||
// ── 12. Extensions ─────────────────────
|
||||
@@ -443,6 +446,19 @@ export function createDomains(restClient) {
|
||||
del: (id) => rc.del(`/api/v1/admin/extensions/${id}`),
|
||||
},
|
||||
|
||||
packages: {
|
||||
list: (opts) => rc.get('/api/v1/admin/packages' + _qs(opts)),
|
||||
get: (id) => rc.get(`/api/v1/admin/packages/${id}`),
|
||||
install: (file) => rc.upload('/api/v1/admin/packages/install', file),
|
||||
enable: (id) => rc.put(`/api/v1/admin/packages/${id}/enable`, {}),
|
||||
disable: (id) => rc.put(`/api/v1/admin/packages/${id}/disable`, {}),
|
||||
del: (id) => rc.del(`/api/v1/admin/packages/${id}`),
|
||||
settings: (id) => rc.get(`/api/v1/admin/packages/${id}/settings`),
|
||||
updateSettings: (id, data) => rc.put(`/api/v1/admin/packages/${id}/settings`, data),
|
||||
registry: () => rc.get('/api/v1/admin/packages/registry'),
|
||||
registryInstall: (url) => rc.post('/api/v1/admin/packages/registry/install', { url }),
|
||||
},
|
||||
|
||||
tasks: {
|
||||
list: () => rc.get('/api/v1/admin/tasks'),
|
||||
run: (id) => rc.post(`/api/v1/admin/tasks/${id}/run`, {}),
|
||||
@@ -478,11 +494,19 @@ export function createDomains(restClient) {
|
||||
// ── Misc (not domain-specific) ─────────
|
||||
folders: {
|
||||
list: () => rc.get('/api/v1/folders'),
|
||||
create: (name, sort) => rc.post('/api/v1/folders', { name, sort_order: sort || 0 }),
|
||||
create: (name, opts) => rc.post('/api/v1/folders', { name, parent_id: opts?.parent_id || null, sort_order: opts?.sort_order || 0 }),
|
||||
update: (id, data) => rc.put(`/api/v1/folders/${id}`, data),
|
||||
del: (id) => rc.del(`/api/v1/folders/${id}`),
|
||||
},
|
||||
|
||||
notifications: {
|
||||
list: (params) => rc.get('/api/v1/notifications', params),
|
||||
unreadCount: () => rc.get('/api/v1/notifications/unread-count'),
|
||||
markRead: (id) => rc.patch(`/api/v1/notifications/${id}/read`),
|
||||
markAllRead: () => rc.post('/api/v1/notifications/mark-all-read'),
|
||||
del: (id) => rc.del(`/api/v1/notifications/${id}`),
|
||||
},
|
||||
|
||||
files: {
|
||||
get: (id) => rc.get(`/api/v1/files/${id}`),
|
||||
del: (id) => rc.del(`/api/v1/files/${id}`),
|
||||
@@ -492,6 +516,11 @@ export function createDomains(restClient) {
|
||||
list: () => rc.get('/api/v1/tools'),
|
||||
},
|
||||
|
||||
// ── Users ──────────────────────────────
|
||||
users: {
|
||||
search: (q) => rc.get('/api/v1/users/search' + _qs({ q })),
|
||||
},
|
||||
|
||||
presence: {
|
||||
heartbeat: () => rc.post('/api/v1/presence/heartbeat', {}),
|
||||
},
|
||||
|
||||
@@ -30,6 +30,7 @@ export function createAuth() {
|
||||
let _policies = {};
|
||||
let _refreshTimer = null;
|
||||
let _refreshPromise = null;
|
||||
let _booting = false;
|
||||
let _restClient = null;
|
||||
let _emit = () => {};
|
||||
|
||||
@@ -69,6 +70,7 @@ export function createAuth() {
|
||||
_groups = [];
|
||||
_policies = {};
|
||||
localStorage.removeItem(_storageKey);
|
||||
sessionStorage.removeItem('sw-chat-active');
|
||||
document.cookie = 'sb_token=; path=/; max-age=0';
|
||||
if (_refreshTimer) { clearTimeout(_refreshTimer); _refreshTimer = null; }
|
||||
}
|
||||
@@ -194,11 +196,19 @@ export function createAuth() {
|
||||
*/
|
||||
async boot() {
|
||||
_loadTokens();
|
||||
if (!_refreshToken) return;
|
||||
if (!_refreshToken) {
|
||||
// No tokens in localStorage — clear any stale sb_token cookie
|
||||
// so Go SSR middleware doesn't trust a leftover cookie.
|
||||
document.cookie = 'sb_token=; path=/; max-age=0';
|
||||
return;
|
||||
}
|
||||
|
||||
// Unknown token age — schedule refresh soon
|
||||
_scheduleRefresh(60);
|
||||
|
||||
// Suppress _on401Failure redirect during boot — boot handles 401 itself.
|
||||
_booting = true;
|
||||
|
||||
// Fetch permissions (validates the access token)
|
||||
try {
|
||||
await _fetchPermissions();
|
||||
@@ -215,6 +225,8 @@ export function createAuth() {
|
||||
// Network error or other — keep tokens, user may be offline
|
||||
console.warn('[sw.auth] Boot: permissions fetch failed (keeping tokens):', e.message);
|
||||
}
|
||||
} finally {
|
||||
_booting = false;
|
||||
}
|
||||
|
||||
if (_accessToken) {
|
||||
@@ -233,8 +245,15 @@ export function createAuth() {
|
||||
|
||||
_on401Failure() {
|
||||
_clearTokens();
|
||||
// During boot(), auth.boot() handles 401 gracefully — don't redirect.
|
||||
if (_booting) return;
|
||||
// Already on login page — don't redirect (prevents blank-page reload loop
|
||||
// when stale localStorage tokens trigger 401 during SDK boot on /login).
|
||||
const base = window.__BASE__ || '';
|
||||
window.location.href = base + '/login';
|
||||
const loginPath = base + '/login';
|
||||
const here = window.location.pathname.replace(/\/+$/, '');
|
||||
if (here === loginPath) return;
|
||||
window.location.href = loginPath;
|
||||
},
|
||||
|
||||
_setAuth(data) { _setAuth(data); },
|
||||
|
||||
@@ -139,7 +139,7 @@ export async function boot() {
|
||||
};
|
||||
|
||||
// Marker for idempotency
|
||||
sw._sdk = '0.37.9';
|
||||
sw._sdk = '0.37.14';
|
||||
|
||||
// 8. Expose globally
|
||||
window.sw = sw;
|
||||
@@ -161,7 +161,7 @@ export async function boot() {
|
||||
// 10. Signal ready
|
||||
events.emit('sdk.ready', {}, { localOnly: true });
|
||||
document.dispatchEvent(new CustomEvent('sw:ready', { detail: { sw } }));
|
||||
console.log('[sw] SDK v0.37.9 ready');
|
||||
console.log(`[sw] SDK v${sw._sdk} ready`);
|
||||
|
||||
return sw;
|
||||
}
|
||||
|
||||
@@ -85,6 +85,12 @@ export function createPipe() {
|
||||
entry.stats.calls++;
|
||||
entry.stats.totalMs += performance.now() - t0;
|
||||
|
||||
if (result instanceof Promise) {
|
||||
console.error(`[sw.pipe] ${stage}: filter '${entry.source}' returned Promise (async not supported)`);
|
||||
entry.stats.errors++;
|
||||
continue;
|
||||
}
|
||||
|
||||
if (result === null || result === undefined) {
|
||||
return null; // halt chain
|
||||
}
|
||||
|
||||
@@ -97,8 +97,10 @@ export function createRestClient(getToken, onRefresh, on401Failure) {
|
||||
if (!text) return null;
|
||||
const json = JSON.parse(text);
|
||||
|
||||
// List envelope: { data: Array, ... }
|
||||
if (json && Array.isArray(json.data) && ('page' in json || 'total' in json || 'per_page' in json)) {
|
||||
// List envelope: { data: Array } with no sibling keys → unwrap.
|
||||
// If siblings exist (total, page, etc.) return full object so
|
||||
// callers can access metadata alongside the list.
|
||||
if (json && Array.isArray(json.data) && Object.keys(json).length === 1) {
|
||||
return json.data;
|
||||
}
|
||||
return json;
|
||||
|
||||
Reference in New Issue
Block a user