@astermind/cybernetic-chatbot-client 2.2.44 → 2.2.48

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -7,13 +7,14 @@
7
7
  // src/ApiClient.ts
8
8
  // HTTP client for AsterMind backend API
9
9
  /**
10
- * Map backend source format to client Source interface
10
+ * Map backend source format to client Source interface.
11
+ * Handles both canonical (title/score) and legacy (heading/no-score) field names.
11
12
  */
12
13
  function mapSource(raw) {
13
14
  return {
14
- title: raw.title,
15
- snippet: raw.content,
16
- relevance: raw.score,
15
+ title: raw.title || raw.heading || 'Document',
16
+ snippet: raw.content || '',
17
+ relevance: raw.score ?? 0,
17
18
  documentId: raw.documentId,
18
19
  fullContent: raw.fullContent,
19
20
  downloadUrl: raw.downloadUrl,
@@ -51,9 +52,10 @@
51
52
  throw new Error(error.message || `HTTP ${response.status}: ${response.statusText}`);
52
53
  }
53
54
  const data = await response.json();
54
- // Map backend source format to client Source interface
55
+ // Normalize response: accept both 'reply' (canonical) and 'answer' (legacy)
55
56
  return {
56
57
  ...data,
58
+ reply: data.reply || data.answer || '',
57
59
  sources: (data.sources || []).map(mapSource)
58
60
  };
59
61
  }
@@ -129,7 +131,8 @@
129
131
  }
130
132
  }
131
133
  /**
132
- * Get general documents for caching
134
+ * Get general documents for caching.
135
+ * Normalizes field names from both canonical (title) and legacy (name) formats.
133
136
  */
134
137
  async getGeneralDocs(since) {
135
138
  const params = new URLSearchParams();
@@ -146,10 +149,16 @@
146
149
  throw new Error(`HTTP ${response.status}`);
147
150
  }
148
151
  const data = await response.json();
149
- return data.documents;
152
+ // Normalize: accept both 'title' (canonical) and 'name' (legacy on-prem)
153
+ return (data.documents || []).map((doc) => ({
154
+ id: doc.id,
155
+ title: doc.title || doc.name || 'Untitled',
156
+ updatedAt: doc.updatedAt || doc.updated_at || new Date().toISOString(),
157
+ }));
150
158
  }
151
159
  /**
152
- * Get API status, quota, and system settings
160
+ * Get API status, quota, and system settings.
161
+ * Normalizes response from both canonical and legacy backend formats.
153
162
  */
154
163
  async getStatus() {
155
164
  const response = await fetch(`${this.baseUrl}/api/external/status`, {
@@ -160,7 +169,38 @@
160
169
  if (!response.ok) {
161
170
  throw new Error(`HTTP ${response.status}`);
162
171
  }
163
- return response.json();
172
+ const data = await response.json();
173
+ // Normalize: accept both canonical (apiKey) and legacy (key) structures
174
+ const apiKeyData = data.apiKey || data.key || {};
175
+ const scopes = apiKeyData.scopes || apiKeyData.permissions || ['chat'];
176
+ // Normalize quota: accept both canonical (perMinute/perDay) and legacy structures
177
+ const quota = data.quota || {};
178
+ const perMinute = quota.perMinute || {
179
+ limit: apiKeyData.rateLimit?.limit || quota.rateLimitPerMinute || 30,
180
+ remaining: apiKeyData.rateLimit?.remaining ?? quota.rateLimitPerMinute ?? 30,
181
+ };
182
+ const perDay = quota.perDay || {
183
+ limit: quota.rateLimitPerDay || perMinute.limit * 60 * 24,
184
+ remaining: quota.rateLimitPerDay || perMinute.limit * 60 * 24,
185
+ };
186
+ // Normalize systemSettings: accept both canonical and legacy (system) structures
187
+ const settings = data.systemSettings || data.system || {};
188
+ const cacheRetentionHours = settings.cacheRetentionHours ??
189
+ (settings.cacheRetentionDays ? settings.cacheRetentionDays * 24 : undefined);
190
+ return {
191
+ status: data.status || 'active',
192
+ apiKey: {
193
+ id: apiKeyData.id || '',
194
+ scopes,
195
+ },
196
+ quota: { perMinute, perDay },
197
+ systemSettings: {
198
+ cacheRetentionHours: cacheRetentionHours ?? 720,
199
+ maintenanceMode: settings.maintenanceMode ?? false,
200
+ maintenanceMessage: settings.maintenanceMessage,
201
+ forceOfflineClients: settings.forceOfflineClients ?? false,
202
+ },
203
+ };
164
204
  }
165
205
  /**
166
206
  * Health check (no auth required)
@@ -1298,12 +1338,13 @@
1298
1338
  if (!Array.isArray(wsSources))
1299
1339
  return [];
1300
1340
  return wsSources.map((s) => ({
1301
- title: s.heading || s.documentName || 'Document',
1341
+ title: s.title || s.heading || s.documentName || 'Document',
1302
1342
  snippet: s.content || '',
1303
1343
  relevance: s.score ?? 0,
1304
1344
  documentId: s.documentId,
1305
1345
  documentName: s.documentName,
1306
- sourceType: 'document',
1346
+ sourceType: s.sourceType || 'document',
1347
+ chunkId: s.chunkId,
1307
1348
  }));
1308
1349
  }
1309
1350
  /**