@astermind/cybernetic-chatbot-client 2.2.59 → 2.2.67
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.
- package/dist/ApiClient.d.ts +1 -0
- package/dist/ApiClient.d.ts.map +1 -1
- package/dist/CyberneticClient.d.ts +31 -0
- package/dist/CyberneticClient.d.ts.map +1 -1
- package/dist/cybernetic-chatbot-client-full.esm.js +298 -7
- package/dist/cybernetic-chatbot-client-full.esm.js.map +1 -1
- package/dist/cybernetic-chatbot-client-full.min.js +1 -1
- package/dist/cybernetic-chatbot-client-full.min.js.map +1 -1
- package/dist/cybernetic-chatbot-client-full.umd.js +298 -7
- package/dist/cybernetic-chatbot-client-full.umd.js.map +1 -1
- package/dist/cybernetic-chatbot-client.esm.js +299 -8
- package/dist/cybernetic-chatbot-client.esm.js.map +1 -1
- package/dist/cybernetic-chatbot-client.min.js +1 -1
- package/dist/cybernetic-chatbot-client.min.js.map +1 -1
- package/dist/cybernetic-chatbot-client.umd.js +299 -7
- package/dist/cybernetic-chatbot-client.umd.js.map +1 -1
- package/dist/index.d.ts +2 -0
- package/dist/index.d.ts.map +1 -1
- package/dist/types.d.ts +5 -0
- package/dist/types.d.ts.map +1 -1
- package/package.json +1 -1
package/dist/ApiClient.d.ts
CHANGED
package/dist/ApiClient.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"ApiClient.d.ts","sourceRoot":"","sources":["../src/ApiClient.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAE,MAAM,EAAE,cAAc,EAAE,MAAM,YAAY,CAAC;AAEzD,UAAU,WAAW;IACjB,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,OAAO,CAAC,EAAE;QACN,WAAW,CAAC,EAAE,MAAM,CAAC;QACrB,SAAS,CAAC,EAAE,MAAM,CAAC;KACtB,CAAC;CACL;AAED,UAAU,YAAY;IAClB,KAAK,EAAE,MAAM,CAAC;IACd,SAAS,EAAE,MAAM,CAAC;IAClB,OAAO,EAAE,MAAM,EAAE,CAAC;IAClB,KAAK,EAAE;QACH,UAAU,EAAE,MAAM,CAAC;QACnB,cAAc,EAAE;YACZ,MAAM,EAAE,MAAM,CAAC;YACf,GAAG,EAAE,MAAM,CAAC;SACf,CAAC;KACL,CAAC;CACL;AAED,UAAU,eAAe;IACrB,OAAO,CAAC,EAAE,CAAC,KAAK,EAAE,MAAM,KAAK,IAAI,CAAC;IAClC,SAAS,CAAC,EAAE,CAAC,OAAO,EAAE,MAAM,EAAE,KAAK,IAAI,CAAC;IACxC,UAAU,CAAC,EAAE,CAAC,IAAI,EAAE;QAAE,QAAQ,EAAE,MAAM,CAAC;QAAC,SAAS,CAAC,EAAE,MAAM,CAAC;QAAC,OAAO,CAAC,EAAE,MAAM,EAAE,CAAA;KAAE,KAAK,IAAI,CAAC;
|
|
1
|
+
{"version":3,"file":"ApiClient.d.ts","sourceRoot":"","sources":["../src/ApiClient.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAE,MAAM,EAAE,cAAc,EAAE,MAAM,YAAY,CAAC;AAEzD,UAAU,WAAW;IACjB,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,OAAO,CAAC,EAAE;QACN,WAAW,CAAC,EAAE,MAAM,CAAC;QACrB,SAAS,CAAC,EAAE,MAAM,CAAC;KACtB,CAAC;CACL;AAED,UAAU,YAAY;IAClB,KAAK,EAAE,MAAM,CAAC;IACd,SAAS,EAAE,MAAM,CAAC;IAClB,OAAO,EAAE,MAAM,EAAE,CAAC;IAClB,KAAK,EAAE;QACH,UAAU,EAAE,MAAM,CAAC;QACnB,cAAc,EAAE;YACZ,MAAM,EAAE,MAAM,CAAC;YACf,GAAG,EAAE,MAAM,CAAC;SACf,CAAC;KACL,CAAC;CACL;AAED,UAAU,eAAe;IACrB,OAAO,CAAC,EAAE,CAAC,KAAK,EAAE,MAAM,KAAK,IAAI,CAAC;IAClC,SAAS,CAAC,EAAE,CAAC,OAAO,EAAE,MAAM,EAAE,KAAK,IAAI,CAAC;IACxC,UAAU,CAAC,EAAE,CAAC,IAAI,EAAE;QAAE,QAAQ,EAAE,MAAM,CAAC;QAAC,SAAS,CAAC,EAAE,MAAM,CAAC;QAAC,SAAS,CAAC,EAAE,MAAM,CAAC;QAAC,OAAO,CAAC,EAAE,MAAM,EAAE,CAAA;KAAE,KAAK,IAAI,CAAC;IAC9G,OAAO,CAAC,EAAE,CAAC,KAAK,EAAE,KAAK,KAAK,IAAI,CAAC;CACpC;AAED,UAAU,cAAc;IACpB,MAAM,EAAE,MAAM,CAAC;IACf,MAAM,EAAE;QAAE,EAAE,EAAE,MAAM,CAAC;QAAC,MAAM,EAAE,MAAM,EAAE,CAAA;KAAE,CAAC;IACzC,KAAK,EAAE;QACH,SAAS,EAAE;YAAE,KAAK,EAAE,MAAM,CAAC;YAAC,SAAS,EAAE,MAAM,CAAA;SAAE,CAAC;QAChD,MAAM,EAAE;YAAE,KAAK,EAAE,MAAM,CAAC;YAAC,SAAS,EAAE,MAAM,CAAA;SAAE,CAAC;KAChD,CAAC;IACF,cAAc,CAAC,EAAE,cAAc,CAAC;CACnC;AAqCD;;GAEG;AACH,qBAAa,SAAS;IAClB,OAAO,CAAC,OAAO,CAAS;IACxB,OAAO,CAAC,MAAM,CAAS;gBAEX,OAAO,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM;IAK3C;;OAEG;IACG,IAAI,CACN,OAAO,EAAE,MAAM,EACf,OAAO,CAAC,EAAE,WAAW,GACtB,OAAO,CAAC,YAAY,CAAC;IA4BxB;;OAEG;IACG,UAAU,CACZ,OAAO,EAAE,MAAM,EACf,OAAO,EAAE,WAAW,GAAG,eAAe,GACvC,OAAO,CAAC,IAAI,CAAC;IAyEhB;;;OAGG;IACG,cAAc,CAAC,KAAK,CAAC,EAAE,MAAM,GAAG,IAAI,GAAG,OAAO,CAAC,KAAK,CAAC;QACvD,EAAE,EAAE,MAAM,CAAC;QACX,KAAK,EAAE,MAAM,CAAC;QACd,SAAS,EAAE,MAAM,CAAC;KACrB,CAAC,CAAC;IA0BH;;;OAGG;IACG,SAAS,IAAI,OAAO,CAAC,cAAc,CAAC;IAiD1C;;OAEG;IACG,MAAM,IAAI,OAAO,CAAC;QAAE,MAAM,EAAE,MAAM,CAAC;QAAC,SAAS,EAAE,MAAM,CAAA;KAAE,CAAC;CASjE"}
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import { CyberneticOfflineStorage } from './CyberneticOfflineStorage.js';
|
|
2
|
+
import type { StoredMessage } from './CyberneticSessionStorage.js';
|
|
2
3
|
import { LicenseManager } from './license/index.js';
|
|
3
4
|
import type { CyberneticConfig, CyberneticResponse, CyberneticError, ConnectionStatus, AskOptions, StreamCallbacks, CacheStatus, SystemSettings, AgenticConfig, SourcesConfig } from './types.js';
|
|
4
5
|
import type { LicenseState } from './license/types.js';
|
|
@@ -33,6 +34,7 @@ export declare class CyberneticClient {
|
|
|
33
34
|
private licenseManager;
|
|
34
35
|
private offlineStorage;
|
|
35
36
|
private omegaRAG;
|
|
37
|
+
private sessionStorage;
|
|
36
38
|
private offlineWarningShown;
|
|
37
39
|
constructor(config: CyberneticConfig);
|
|
38
40
|
/**
|
|
@@ -174,6 +176,35 @@ export declare class CyberneticClient {
|
|
|
174
176
|
* Get offline storage instance for advanced operations
|
|
175
177
|
*/
|
|
176
178
|
getOfflineStorage(): CyberneticOfflineStorage | null;
|
|
179
|
+
/**
|
|
180
|
+
* Get stored messages from a previous session for UI restoration.
|
|
181
|
+
* Call after construction to check for resumable conversations.
|
|
182
|
+
*/
|
|
183
|
+
getStoredMessages(): StoredMessage[];
|
|
184
|
+
/**
|
|
185
|
+
* Check if a valid stored session exists that can be resumed.
|
|
186
|
+
*/
|
|
187
|
+
hasStoredSession(): boolean;
|
|
188
|
+
/**
|
|
189
|
+
* Get session info for debugging/status display.
|
|
190
|
+
*/
|
|
191
|
+
getSessionInfo(): {
|
|
192
|
+
hasSession: boolean;
|
|
193
|
+
sessionId: string | null;
|
|
194
|
+
messageCount: number;
|
|
195
|
+
lastUpdated: Date | null;
|
|
196
|
+
ttlRemaining: number | null;
|
|
197
|
+
};
|
|
198
|
+
/**
|
|
199
|
+
* Clear the stored session and start fresh.
|
|
200
|
+
* Use for "New Conversation" actions.
|
|
201
|
+
*/
|
|
202
|
+
clearSession(): void;
|
|
203
|
+
/**
|
|
204
|
+
* Start a new session, clearing any stored data.
|
|
205
|
+
* Optionally sets a new sessionId immediately.
|
|
206
|
+
*/
|
|
207
|
+
startNewSession(sessionId?: string): void;
|
|
177
208
|
/**
|
|
178
209
|
* Send a message to the chatbot
|
|
179
210
|
* Always returns a response, never throws
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"CyberneticClient.d.ts","sourceRoot":"","sources":["../src/CyberneticClient.ts"],"names":[],"mappings":"AAMA,OAAO,EAAE,wBAAwB,EAAE,MAAM,+BAA+B,CAAC;AAGzE,OAAO,EAAE,cAAc,EAAE,MAAM,oBAAoB,CAAC;AACpD,OAAO,KAAK,EACR,gBAAgB,EAChB,kBAAkB,EAClB,eAAe,EACf,gBAAgB,EAChB,UAAU,EACV,eAAe,EACf,WAAW,EACX,cAAc,EACd,aAAa,EAIb,aAAa,EAEhB,MAAM,YAAY,CAAC;AACpB,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,oBAAoB,CAAC;AAGvD;;;GAGG;AACH,MAAM,WAAW,mBAAmB;IAChC,iDAAiD;IAEjD,KAAK,EAAE,GAAG,CAAC;IACX,4DAA4D;IAE5D,gBAAgB,CAAC,EAAE,GAAG,CAAC;CAC1B;AA6BD;;;;;GAKG;AACH,qBAAa,gBAAgB;IACzB,OAAO,CAAC,MAAM,CAAiB;IAC/B,OAAO,CAAC,SAAS,CAAY;IAC7B,OAAO,CAAC,WAAW,CAAmC;IACtD,OAAO,CAAC,KAAK,CAAkB;IAC/B,OAAO,CAAC,QAAQ,CAAqB;IACrC,OAAO,CAAC,MAAM,CAAkC;IAChD,OAAO,CAAC,SAAS,CAAgC;IAGjD,OAAO,CAAC,cAAc,CAA+B;IACrD,OAAO,CAAC,mBAAmB,CAAa;IACxC,OAAO,CAAC,QAAQ,CAAC,uBAAuB,CAAU;IAGlD,OAAO,CAAC,mBAAmB,CAAoC;IAG/D,OAAO,CAAC,cAAc,CAAiB;IAGvC,OAAO,CAAC,cAAc,CAAyC;IAG/D,OAAO,CAAC,QAAQ,CAAgC;IAGhD,OAAO,CAAC,mBAAmB,CAAS;gBAExB,MAAM,EAAE,gBAAgB;
|
|
1
|
+
{"version":3,"file":"CyberneticClient.d.ts","sourceRoot":"","sources":["../src/CyberneticClient.ts"],"names":[],"mappings":"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"}
|
|
@@ -85,6 +85,7 @@ class ApiClient {
|
|
|
85
85
|
let fullText = '';
|
|
86
86
|
let sources = [];
|
|
87
87
|
let sessionId;
|
|
88
|
+
let messageId;
|
|
88
89
|
try {
|
|
89
90
|
while (true) {
|
|
90
91
|
const { done, value } = await reader.read();
|
|
@@ -113,6 +114,7 @@ class ApiClient {
|
|
|
113
114
|
else if (data.sessionId !== undefined) {
|
|
114
115
|
// Done event
|
|
115
116
|
sessionId = data.sessionId;
|
|
117
|
+
messageId = data.messageId;
|
|
116
118
|
}
|
|
117
119
|
}
|
|
118
120
|
catch {
|
|
@@ -121,7 +123,7 @@ class ApiClient {
|
|
|
121
123
|
}
|
|
122
124
|
}
|
|
123
125
|
}
|
|
124
|
-
options.onComplete?.({ fullText, sessionId, sources });
|
|
126
|
+
options.onComplete?.({ fullText, sessionId, messageId, sources });
|
|
125
127
|
}
|
|
126
128
|
catch (error) {
|
|
127
129
|
options.onError?.(error);
|
|
@@ -1374,6 +1376,230 @@ class WebSocketTransport {
|
|
|
1374
1376
|
}
|
|
1375
1377
|
}
|
|
1376
1378
|
|
|
1379
|
+
// src/CyberneticSessionStorage.ts
|
|
1380
|
+
// Session storage manager for persisting chatbot session across page navigations
|
|
1381
|
+
const DEFAULT_CONFIG = {
|
|
1382
|
+
enabled: true,
|
|
1383
|
+
storageKey: 'astermind_session',
|
|
1384
|
+
sessionTtl: 30 * 60 * 1000, // 30 minutes
|
|
1385
|
+
persistMessages: true,
|
|
1386
|
+
maxMessages: 50
|
|
1387
|
+
};
|
|
1388
|
+
/**
|
|
1389
|
+
* Session storage manager for persisting chatbot sessions
|
|
1390
|
+
*
|
|
1391
|
+
* Uses sessionStorage to maintain conversation continuity across
|
|
1392
|
+
* page navigations within the same browser session.
|
|
1393
|
+
*/
|
|
1394
|
+
class CyberneticSessionStorage {
|
|
1395
|
+
constructor(config) {
|
|
1396
|
+
this.cachedSession = null;
|
|
1397
|
+
this.config = { ...DEFAULT_CONFIG, ...config };
|
|
1398
|
+
// Load cached session on initialization
|
|
1399
|
+
if (this.config.enabled && this.isAvailable()) {
|
|
1400
|
+
this.cachedSession = this.loadFromStorage();
|
|
1401
|
+
}
|
|
1402
|
+
}
|
|
1403
|
+
/**
|
|
1404
|
+
* Check if sessionStorage is available
|
|
1405
|
+
*/
|
|
1406
|
+
isAvailable() {
|
|
1407
|
+
if (typeof window === 'undefined')
|
|
1408
|
+
return false;
|
|
1409
|
+
try {
|
|
1410
|
+
const testKey = '__astermind_test__';
|
|
1411
|
+
window.sessionStorage.setItem(testKey, 'test');
|
|
1412
|
+
window.sessionStorage.removeItem(testKey);
|
|
1413
|
+
return true;
|
|
1414
|
+
}
|
|
1415
|
+
catch {
|
|
1416
|
+
return false;
|
|
1417
|
+
}
|
|
1418
|
+
}
|
|
1419
|
+
/**
|
|
1420
|
+
* Get the current session ID (if valid)
|
|
1421
|
+
*/
|
|
1422
|
+
getSessionId() {
|
|
1423
|
+
if (!this.config.enabled)
|
|
1424
|
+
return null;
|
|
1425
|
+
const session = this.getSession();
|
|
1426
|
+
return session?.sessionId ?? null;
|
|
1427
|
+
}
|
|
1428
|
+
/**
|
|
1429
|
+
* Get the full stored session (if valid)
|
|
1430
|
+
*/
|
|
1431
|
+
getSession() {
|
|
1432
|
+
if (!this.config.enabled)
|
|
1433
|
+
return null;
|
|
1434
|
+
// Use cached session if available
|
|
1435
|
+
if (this.cachedSession) {
|
|
1436
|
+
if (this.isSessionValid(this.cachedSession)) {
|
|
1437
|
+
return this.cachedSession;
|
|
1438
|
+
}
|
|
1439
|
+
// Session expired, clear it
|
|
1440
|
+
this.clear();
|
|
1441
|
+
return null;
|
|
1442
|
+
}
|
|
1443
|
+
// Try loading from storage
|
|
1444
|
+
const session = this.loadFromStorage();
|
|
1445
|
+
if (session && this.isSessionValid(session)) {
|
|
1446
|
+
this.cachedSession = session;
|
|
1447
|
+
return session;
|
|
1448
|
+
}
|
|
1449
|
+
return null;
|
|
1450
|
+
}
|
|
1451
|
+
/**
|
|
1452
|
+
* Save/update session ID
|
|
1453
|
+
*/
|
|
1454
|
+
saveSessionId(sessionId) {
|
|
1455
|
+
if (!this.config.enabled || !sessionId)
|
|
1456
|
+
return;
|
|
1457
|
+
const existingSession = this.getSession();
|
|
1458
|
+
const session = {
|
|
1459
|
+
sessionId,
|
|
1460
|
+
updatedAt: Date.now(),
|
|
1461
|
+
messages: existingSession?.messages ?? []
|
|
1462
|
+
};
|
|
1463
|
+
this.saveToStorage(session);
|
|
1464
|
+
this.cachedSession = session;
|
|
1465
|
+
}
|
|
1466
|
+
/**
|
|
1467
|
+
* Add a message to the conversation history
|
|
1468
|
+
*/
|
|
1469
|
+
addMessage(message) {
|
|
1470
|
+
if (!this.config.enabled || !this.config.persistMessages)
|
|
1471
|
+
return;
|
|
1472
|
+
const session = this.getSession();
|
|
1473
|
+
if (!session)
|
|
1474
|
+
return;
|
|
1475
|
+
const newMessage = {
|
|
1476
|
+
...message,
|
|
1477
|
+
id: this.generateMessageId(),
|
|
1478
|
+
timestamp: Date.now()
|
|
1479
|
+
};
|
|
1480
|
+
// Add new message and trim if necessary
|
|
1481
|
+
session.messages = session.messages ?? [];
|
|
1482
|
+
session.messages.push(newMessage);
|
|
1483
|
+
// Keep only the most recent messages
|
|
1484
|
+
if (session.messages.length > this.config.maxMessages) {
|
|
1485
|
+
session.messages = session.messages.slice(-this.config.maxMessages);
|
|
1486
|
+
}
|
|
1487
|
+
session.updatedAt = Date.now();
|
|
1488
|
+
this.saveToStorage(session);
|
|
1489
|
+
this.cachedSession = session;
|
|
1490
|
+
}
|
|
1491
|
+
/**
|
|
1492
|
+
* Get conversation messages
|
|
1493
|
+
*/
|
|
1494
|
+
getMessages() {
|
|
1495
|
+
if (!this.config.enabled || !this.config.persistMessages)
|
|
1496
|
+
return [];
|
|
1497
|
+
const session = this.getSession();
|
|
1498
|
+
return session?.messages ?? [];
|
|
1499
|
+
}
|
|
1500
|
+
/**
|
|
1501
|
+
* Clear the stored session
|
|
1502
|
+
*/
|
|
1503
|
+
clear() {
|
|
1504
|
+
this.cachedSession = null;
|
|
1505
|
+
if (!this.isAvailable())
|
|
1506
|
+
return;
|
|
1507
|
+
try {
|
|
1508
|
+
window.sessionStorage.removeItem(this.config.storageKey);
|
|
1509
|
+
}
|
|
1510
|
+
catch (error) {
|
|
1511
|
+
console.warn('[CyberneticSessionStorage] Failed to clear session:', error);
|
|
1512
|
+
}
|
|
1513
|
+
}
|
|
1514
|
+
/**
|
|
1515
|
+
* Start a new session (clears existing and optionally sets new ID)
|
|
1516
|
+
*/
|
|
1517
|
+
startNewSession(sessionId) {
|
|
1518
|
+
this.clear();
|
|
1519
|
+
if (sessionId) {
|
|
1520
|
+
this.saveSessionId(sessionId);
|
|
1521
|
+
}
|
|
1522
|
+
}
|
|
1523
|
+
/**
|
|
1524
|
+
* Check if we have a valid stored session
|
|
1525
|
+
*/
|
|
1526
|
+
hasValidSession() {
|
|
1527
|
+
return this.getSession() !== null;
|
|
1528
|
+
}
|
|
1529
|
+
/**
|
|
1530
|
+
* Get session info for debugging/status
|
|
1531
|
+
*/
|
|
1532
|
+
getSessionInfo() {
|
|
1533
|
+
const session = this.getSession();
|
|
1534
|
+
if (!session) {
|
|
1535
|
+
return {
|
|
1536
|
+
hasSession: false,
|
|
1537
|
+
sessionId: null,
|
|
1538
|
+
messageCount: 0,
|
|
1539
|
+
lastUpdated: null,
|
|
1540
|
+
ttlRemaining: null
|
|
1541
|
+
};
|
|
1542
|
+
}
|
|
1543
|
+
const ttlRemaining = Math.max(0, this.config.sessionTtl - (Date.now() - session.updatedAt));
|
|
1544
|
+
return {
|
|
1545
|
+
hasSession: true,
|
|
1546
|
+
sessionId: session.sessionId,
|
|
1547
|
+
messageCount: session.messages?.length ?? 0,
|
|
1548
|
+
lastUpdated: new Date(session.updatedAt),
|
|
1549
|
+
ttlRemaining
|
|
1550
|
+
};
|
|
1551
|
+
}
|
|
1552
|
+
// ==================== PRIVATE METHODS ====================
|
|
1553
|
+
/**
|
|
1554
|
+
* Check if a session is still valid (not expired)
|
|
1555
|
+
*/
|
|
1556
|
+
isSessionValid(session) {
|
|
1557
|
+
const age = Date.now() - session.updatedAt;
|
|
1558
|
+
return age < this.config.sessionTtl;
|
|
1559
|
+
}
|
|
1560
|
+
/**
|
|
1561
|
+
* Load session from sessionStorage
|
|
1562
|
+
*/
|
|
1563
|
+
loadFromStorage() {
|
|
1564
|
+
if (!this.isAvailable())
|
|
1565
|
+
return null;
|
|
1566
|
+
try {
|
|
1567
|
+
const stored = window.sessionStorage.getItem(this.config.storageKey);
|
|
1568
|
+
if (!stored)
|
|
1569
|
+
return null;
|
|
1570
|
+
const session = JSON.parse(stored);
|
|
1571
|
+
// Validate structure
|
|
1572
|
+
if (!session.sessionId || typeof session.updatedAt !== 'number') {
|
|
1573
|
+
return null;
|
|
1574
|
+
}
|
|
1575
|
+
return session;
|
|
1576
|
+
}
|
|
1577
|
+
catch (error) {
|
|
1578
|
+
console.warn('[CyberneticSessionStorage] Failed to load session:', error);
|
|
1579
|
+
return null;
|
|
1580
|
+
}
|
|
1581
|
+
}
|
|
1582
|
+
/**
|
|
1583
|
+
* Save session to sessionStorage
|
|
1584
|
+
*/
|
|
1585
|
+
saveToStorage(session) {
|
|
1586
|
+
if (!this.isAvailable())
|
|
1587
|
+
return;
|
|
1588
|
+
try {
|
|
1589
|
+
window.sessionStorage.setItem(this.config.storageKey, JSON.stringify(session));
|
|
1590
|
+
}
|
|
1591
|
+
catch (error) {
|
|
1592
|
+
console.warn('[CyberneticSessionStorage] Failed to save session:', error);
|
|
1593
|
+
}
|
|
1594
|
+
}
|
|
1595
|
+
/**
|
|
1596
|
+
* Generate a unique message ID
|
|
1597
|
+
*/
|
|
1598
|
+
generateMessageId() {
|
|
1599
|
+
return `msg_${Date.now()}_${Math.random().toString(36).substr(2, 9)}`;
|
|
1600
|
+
}
|
|
1601
|
+
}
|
|
1602
|
+
|
|
1377
1603
|
// src/config.ts
|
|
1378
1604
|
// Configuration loading and validation
|
|
1379
1605
|
/** Default API URL when not specified */
|
|
@@ -2338,6 +2564,8 @@ class CyberneticClient {
|
|
|
2338
2564
|
licenseKey: config.licenseKey,
|
|
2339
2565
|
environment: config.environment,
|
|
2340
2566
|
});
|
|
2567
|
+
// Initialize session storage (auto-loads existing session from browser sessionStorage)
|
|
2568
|
+
this.sessionStorage = new CyberneticSessionStorage(config.session);
|
|
2341
2569
|
// Verify license asynchronously (non-blocking)
|
|
2342
2570
|
this.licenseManager.verify().then(() => {
|
|
2343
2571
|
// Check client feature after verification
|
|
@@ -2638,6 +2866,40 @@ class CyberneticClient {
|
|
|
2638
2866
|
getOfflineStorage() {
|
|
2639
2867
|
return this.offlineStorage;
|
|
2640
2868
|
}
|
|
2869
|
+
// ==================== SESSION PERSISTENCE METHODS (ADR-028) ====================
|
|
2870
|
+
/**
|
|
2871
|
+
* Get stored messages from a previous session for UI restoration.
|
|
2872
|
+
* Call after construction to check for resumable conversations.
|
|
2873
|
+
*/
|
|
2874
|
+
getStoredMessages() {
|
|
2875
|
+
return this.sessionStorage.getMessages();
|
|
2876
|
+
}
|
|
2877
|
+
/**
|
|
2878
|
+
* Check if a valid stored session exists that can be resumed.
|
|
2879
|
+
*/
|
|
2880
|
+
hasStoredSession() {
|
|
2881
|
+
return this.sessionStorage.hasValidSession();
|
|
2882
|
+
}
|
|
2883
|
+
/**
|
|
2884
|
+
* Get session info for debugging/status display.
|
|
2885
|
+
*/
|
|
2886
|
+
getSessionInfo() {
|
|
2887
|
+
return this.sessionStorage.getSessionInfo();
|
|
2888
|
+
}
|
|
2889
|
+
/**
|
|
2890
|
+
* Clear the stored session and start fresh.
|
|
2891
|
+
* Use for "New Conversation" actions.
|
|
2892
|
+
*/
|
|
2893
|
+
clearSession() {
|
|
2894
|
+
this.sessionStorage.clear();
|
|
2895
|
+
}
|
|
2896
|
+
/**
|
|
2897
|
+
* Start a new session, clearing any stored data.
|
|
2898
|
+
* Optionally sets a new sessionId immediately.
|
|
2899
|
+
*/
|
|
2900
|
+
startNewSession(sessionId) {
|
|
2901
|
+
this.sessionStorage.startNewSession(sessionId);
|
|
2902
|
+
}
|
|
2641
2903
|
// ==================== CORE METHODS ====================
|
|
2642
2904
|
/**
|
|
2643
2905
|
* Send a message to the chatbot
|
|
@@ -2651,6 +2913,11 @@ class CyberneticClient {
|
|
|
2651
2913
|
if (!message || typeof message !== 'string') {
|
|
2652
2914
|
return this.createErrorResponse('Message is required', 'none');
|
|
2653
2915
|
}
|
|
2916
|
+
// Auto-resolve sessionId: explicit option > stored session > none (ADR-028)
|
|
2917
|
+
const resolvedSessionId = options?.sessionId ?? this.sessionStorage.getSessionId() ?? undefined;
|
|
2918
|
+
const resolvedOptions = resolvedSessionId
|
|
2919
|
+
? { ...options, sessionId: resolvedSessionId }
|
|
2920
|
+
: options;
|
|
2654
2921
|
// Check maintenance mode before API call (ADR-200)
|
|
2655
2922
|
const settings = await this.checkSystemStatus();
|
|
2656
2923
|
if (settings.maintenanceMode || settings.forceOfflineClients) {
|
|
@@ -2671,10 +2938,16 @@ class CyberneticClient {
|
|
|
2671
2938
|
}
|
|
2672
2939
|
// Try API first
|
|
2673
2940
|
try {
|
|
2674
|
-
const response = await this.apiWithRetry(message,
|
|
2941
|
+
const response = await this.apiWithRetry(message, resolvedOptions);
|
|
2675
2942
|
this.setStatus('online');
|
|
2676
2943
|
// Process response through license manager (may add warning in production)
|
|
2677
2944
|
const processedReply = this.licenseManager.processResponse(response.reply);
|
|
2945
|
+
// Persist session state (ADR-028)
|
|
2946
|
+
if (response.sessionId) {
|
|
2947
|
+
this.sessionStorage.saveSessionId(response.sessionId);
|
|
2948
|
+
}
|
|
2949
|
+
this.sessionStorage.addMessage({ role: 'user', content: message });
|
|
2950
|
+
this.sessionStorage.addMessage({ role: 'assistant', content: processedReply, confidence: 'high' });
|
|
2678
2951
|
return {
|
|
2679
2952
|
reply: processedReply,
|
|
2680
2953
|
confidence: 'high',
|
|
@@ -2720,6 +2993,13 @@ class CyberneticClient {
|
|
|
2720
2993
|
});
|
|
2721
2994
|
return;
|
|
2722
2995
|
}
|
|
2996
|
+
// Auto-resolve sessionId: explicit option > stored session > none (ADR-028)
|
|
2997
|
+
const resolvedSessionId = options?.sessionId ?? this.sessionStorage.getSessionId() ?? undefined;
|
|
2998
|
+
const resolvedOptions = resolvedSessionId
|
|
2999
|
+
? { ...options, sessionId: resolvedSessionId }
|
|
3000
|
+
: options;
|
|
3001
|
+
// Save user message immediately (ADR-028)
|
|
3002
|
+
this.sessionStorage.addMessage({ role: 'user', content: message });
|
|
2723
3003
|
// Check maintenance mode before API call (ADR-200)
|
|
2724
3004
|
const settings = await this.checkSystemStatus();
|
|
2725
3005
|
if (settings.maintenanceMode || settings.forceOfflineClients) {
|
|
@@ -2732,14 +3012,19 @@ class CyberneticClient {
|
|
|
2732
3012
|
if (this.wsTransport && this.config.transport !== 'rest') {
|
|
2733
3013
|
try {
|
|
2734
3014
|
await this.wsTransport.chatStream(message, {
|
|
2735
|
-
sessionId:
|
|
2736
|
-
context:
|
|
3015
|
+
sessionId: resolvedOptions?.sessionId,
|
|
3016
|
+
context: resolvedOptions?.context,
|
|
2737
3017
|
onToken: callbacks.onToken,
|
|
2738
3018
|
onSources: callbacks.onSources,
|
|
2739
3019
|
onComplete: (response) => {
|
|
2740
3020
|
this.setStatus('online');
|
|
2741
3021
|
// Process through license manager
|
|
2742
3022
|
const processedReply = this.licenseManager.processResponse(response.reply);
|
|
3023
|
+
// Persist session state (ADR-028)
|
|
3024
|
+
if (response.sessionId) {
|
|
3025
|
+
this.sessionStorage.saveSessionId(response.sessionId);
|
|
3026
|
+
}
|
|
3027
|
+
this.sessionStorage.addMessage({ role: 'assistant', content: processedReply, confidence: 'high' });
|
|
2743
3028
|
callbacks.onComplete?.({
|
|
2744
3029
|
...response,
|
|
2745
3030
|
reply: processedReply
|
|
@@ -2749,7 +3034,7 @@ class CyberneticClient {
|
|
|
2749
3034
|
// In 'auto' mode, fall back to SSE on WS error
|
|
2750
3035
|
if (this.config.transport === 'auto') {
|
|
2751
3036
|
console.warn('[Cybernetic] WebSocket error, falling back to SSE:', error.message);
|
|
2752
|
-
this.streamViaSSE(message, callbacks,
|
|
3037
|
+
this.streamViaSSE(message, callbacks, resolvedOptions);
|
|
2753
3038
|
}
|
|
2754
3039
|
else {
|
|
2755
3040
|
// 'websocket' mode — no fallback
|
|
@@ -2775,7 +3060,7 @@ class CyberneticClient {
|
|
|
2775
3060
|
}
|
|
2776
3061
|
}
|
|
2777
3062
|
// REST+SSE path (on-prem, or fallback from WebSocket)
|
|
2778
|
-
await this.streamViaSSE(message, callbacks,
|
|
3063
|
+
await this.streamViaSSE(message, callbacks, resolvedOptions);
|
|
2779
3064
|
}
|
|
2780
3065
|
/**
|
|
2781
3066
|
* Stream chat via REST+SSE (original transport).
|
|
@@ -2792,12 +3077,18 @@ class CyberneticClient {
|
|
|
2792
3077
|
this.setStatus('online');
|
|
2793
3078
|
// Process response through license manager (may add warning in production)
|
|
2794
3079
|
const processedReply = this.licenseManager.processResponse(data.fullText);
|
|
3080
|
+
// Persist session state (ADR-028)
|
|
3081
|
+
if (data.sessionId) {
|
|
3082
|
+
this.sessionStorage.saveSessionId(data.sessionId);
|
|
3083
|
+
}
|
|
3084
|
+
this.sessionStorage.addMessage({ role: 'assistant', content: processedReply, confidence: 'high' });
|
|
2795
3085
|
callbacks.onComplete?.({
|
|
2796
3086
|
reply: processedReply,
|
|
2797
3087
|
confidence: 'high',
|
|
2798
3088
|
sources: data.sources || [],
|
|
2799
3089
|
offline: false,
|
|
2800
|
-
sessionId: data.sessionId
|
|
3090
|
+
sessionId: data.sessionId,
|
|
3091
|
+
messageId: data.messageId
|
|
2801
3092
|
});
|
|
2802
3093
|
},
|
|
2803
3094
|
onError: (error) => {
|