@fiodos/web-core 0.1.11 → 0.1.12
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/cjs/config/types.d.ts +6 -0
- package/dist/cjs/controller/AgentController.d.ts +21 -1
- package/dist/cjs/controller/AgentController.js +60 -3
- package/dist/cjs/dropin/createFiodosAgent.d.ts +5 -0
- package/dist/cjs/dropin/createFiodosAgent.js +7 -0
- package/dist/cjs/version.d.ts +1 -1
- package/dist/cjs/version.js +1 -1
- package/dist/esm/config/types.d.ts +6 -0
- package/dist/esm/controller/AgentController.d.ts +21 -1
- package/dist/esm/controller/AgentController.js +61 -4
- package/dist/esm/dropin/createFiodosAgent.d.ts +5 -0
- package/dist/esm/dropin/createFiodosAgent.js +7 -0
- package/dist/esm/version.d.ts +1 -1
- package/dist/esm/version.js +1 -1
- package/package.json +2 -2
|
@@ -56,6 +56,12 @@ export interface FiodosWebAgentConfig {
|
|
|
56
56
|
telemetry?: TelemetryAdapter;
|
|
57
57
|
/** Host auth check, required by manifest actions declaring requiresAuth. */
|
|
58
58
|
isAuthenticated?: () => boolean;
|
|
59
|
+
/**
|
|
60
|
+
* Host end-user identity. Conversation memory is namespaced per identity
|
|
61
|
+
* (hashed LOCALLY, never sent by this module): logout/account switches swap
|
|
62
|
+
* to that identity's own conversation instead of leaking the previous one.
|
|
63
|
+
*/
|
|
64
|
+
getUserId?: () => string | null;
|
|
59
65
|
messages?: {
|
|
60
66
|
catalogs?: Record<string, MessageCatalog>;
|
|
61
67
|
overrides?: Partial<AgentMessages>;
|
|
@@ -89,7 +89,7 @@ export declare class AgentController {
|
|
|
89
89
|
private consentModalVisible;
|
|
90
90
|
private readonly sessionId;
|
|
91
91
|
private sessionStarted;
|
|
92
|
-
private
|
|
92
|
+
private conversation;
|
|
93
93
|
private pending;
|
|
94
94
|
private confirmationReasked;
|
|
95
95
|
private confirmationVoiceActive;
|
|
@@ -116,6 +116,10 @@ export declare class AgentController {
|
|
|
116
116
|
/** Persistence scope: internal orbs keep their memory under a separate key
|
|
117
117
|
* so a public orb sharing the same appId can never read it. */
|
|
118
118
|
private conversationScope;
|
|
119
|
+
/** Current identity segment (LOCAL hash of the host's getUserId; never sent
|
|
120
|
+
* anywhere). The conversation belongs to (app, scope, identity). */
|
|
121
|
+
private conversationIdentity;
|
|
122
|
+
private removeIdentityListeners;
|
|
119
123
|
private loadingOlderExchanges;
|
|
120
124
|
private loadOlderTimer;
|
|
121
125
|
private readonly listeners;
|
|
@@ -123,6 +127,22 @@ export declare class AgentController {
|
|
|
123
127
|
constructor(config: FiodosWebAgentConfig);
|
|
124
128
|
private restorePersistedConversation;
|
|
125
129
|
private persistConversation;
|
|
130
|
+
/**
|
|
131
|
+
* Re-evaluates the host identity and, when it changed, swaps conversations:
|
|
132
|
+
* the outgoing identity's session is saved under ITS private key (so a user
|
|
133
|
+
* who logs back in recovers it, honouring "never clear"), all in-memory
|
|
134
|
+
* state and UI are wiped, and the incoming identity's own session (usually
|
|
135
|
+
* empty) is restored. An anonymous visitor after a logout always starts
|
|
136
|
+
* clean — the previous user's transcript is never inherited.
|
|
137
|
+
*/
|
|
138
|
+
private syncConversationIdentity;
|
|
139
|
+
/**
|
|
140
|
+
* Wipes the CURRENT identity's conversation: live memory, panel and the
|
|
141
|
+
* persisted blob. Hosts can call it from their logout for a hard wipe (by
|
|
142
|
+
* default a logout only parks the conversation under the user's private
|
|
143
|
+
* local key).
|
|
144
|
+
*/
|
|
145
|
+
resetConversation(): void;
|
|
126
146
|
getState(): AgentState;
|
|
127
147
|
/** Update the REAL live activity and re-render (no-op when unchanged). */
|
|
128
148
|
private setActivity;
|
|
@@ -43,6 +43,7 @@ class AgentController {
|
|
|
43
43
|
this.consentModalVisible = false;
|
|
44
44
|
this.sessionId = randomSessionId();
|
|
45
45
|
this.sessionStarted = false;
|
|
46
|
+
// Replaced wholesale on identity swaps / explicit resets.
|
|
46
47
|
this.conversation = (0, core_1.createConversationSession)();
|
|
47
48
|
this.pending = null;
|
|
48
49
|
this.confirmationReasked = false;
|
|
@@ -72,6 +73,7 @@ class AgentController {
|
|
|
72
73
|
/** Persistence scope: internal orbs keep their memory under a separate key
|
|
73
74
|
* so a public orb sharing the same appId can never read it. */
|
|
74
75
|
this.conversationScope = 'public';
|
|
76
|
+
this.removeIdentityListeners = null;
|
|
75
77
|
this.loadingOlderExchanges = false;
|
|
76
78
|
this.loadOlderTimer = null;
|
|
77
79
|
this.listeners = new Set();
|
|
@@ -131,15 +133,29 @@ class AgentController {
|
|
|
131
133
|
});
|
|
132
134
|
// Re-emit combined state whenever the speech machine advances.
|
|
133
135
|
this.unsubscribeSpeech = this.speech.subscribe(() => this.emit());
|
|
136
|
+
this.conversationIdentity = (0, core_1.conversationIdentityKey)(config.getUserId?.());
|
|
134
137
|
// Rehydrate the previous conversation (page reloads): the persisted blob
|
|
135
138
|
// carries its own retention rule, so expiry is decided correctly even
|
|
136
139
|
// before the published config arrives. Best-effort and non-blocking.
|
|
137
140
|
void this.restorePersistedConversation();
|
|
141
|
+
// Logout/login usually happens on another screen: re-check identity when
|
|
142
|
+
// the tab regains focus or becomes visible again, besides before every turn.
|
|
143
|
+
if (typeof window !== 'undefined') {
|
|
144
|
+
const check = () => void this.syncConversationIdentity();
|
|
145
|
+
window.addEventListener('focus', check);
|
|
146
|
+
document.addEventListener('visibilitychange', check);
|
|
147
|
+
this.removeIdentityListeners = () => {
|
|
148
|
+
window.removeEventListener('focus', check);
|
|
149
|
+
document.removeEventListener('visibilitychange', check);
|
|
150
|
+
};
|
|
151
|
+
}
|
|
138
152
|
}
|
|
139
153
|
// ── Conversation persistence (survives page reloads) ───────────────────────
|
|
140
154
|
async restorePersistedConversation() {
|
|
141
|
-
const
|
|
142
|
-
|
|
155
|
+
const identityAtStart = this.conversationIdentity;
|
|
156
|
+
const restored = await (0, core_1.restoreConversationSession)(this.config.storage, this.config.manifest.appId, Date.now(), this.conversationScope, identityAtStart);
|
|
157
|
+
// The identity may have changed again while the read resolved.
|
|
158
|
+
if (!restored || this.conversationIdentity !== identityAtStart)
|
|
143
159
|
return;
|
|
144
160
|
// Never clobber turns the user already made while the restore resolved.
|
|
145
161
|
if (this.conversation.turns.length > 0 || this.conversation.uiArchive?.length)
|
|
@@ -151,7 +167,43 @@ class AgentController {
|
|
|
151
167
|
this.emit();
|
|
152
168
|
}
|
|
153
169
|
persistConversation() {
|
|
154
|
-
void (0, core_1.persistConversationSession)(this.config.storage, this.config.manifest.appId, this.conversation, this.conversationRetentionMinutes, this.conversationScope);
|
|
170
|
+
void (0, core_1.persistConversationSession)(this.config.storage, this.config.manifest.appId, this.conversation, this.conversationRetentionMinutes, this.conversationScope, this.conversationIdentity);
|
|
171
|
+
}
|
|
172
|
+
/**
|
|
173
|
+
* Re-evaluates the host identity and, when it changed, swaps conversations:
|
|
174
|
+
* the outgoing identity's session is saved under ITS private key (so a user
|
|
175
|
+
* who logs back in recovers it, honouring "never clear"), all in-memory
|
|
176
|
+
* state and UI are wiped, and the incoming identity's own session (usually
|
|
177
|
+
* empty) is restored. An anonymous visitor after a logout always starts
|
|
178
|
+
* clean — the previous user's transcript is never inherited.
|
|
179
|
+
*/
|
|
180
|
+
syncConversationIdentity() {
|
|
181
|
+
const next = (0, core_1.conversationIdentityKey)(this.config.getUserId?.());
|
|
182
|
+
if (next === this.conversationIdentity)
|
|
183
|
+
return false;
|
|
184
|
+
// 1. Park the outgoing identity's session under its own key.
|
|
185
|
+
this.persistConversation();
|
|
186
|
+
// 2. Wipe every trace from memory and the panel.
|
|
187
|
+
this.conversation = (0, core_1.createConversationSession)();
|
|
188
|
+
this.conversationIdentity = next;
|
|
189
|
+
this.lastExchange = null;
|
|
190
|
+
this.emit();
|
|
191
|
+
// 3. Bring in the new identity's own session, if any.
|
|
192
|
+
void this.restorePersistedConversation();
|
|
193
|
+
return true;
|
|
194
|
+
}
|
|
195
|
+
/**
|
|
196
|
+
* Wipes the CURRENT identity's conversation: live memory, panel and the
|
|
197
|
+
* persisted blob. Hosts can call it from their logout for a hard wipe (by
|
|
198
|
+
* default a logout only parks the conversation under the user's private
|
|
199
|
+
* local key).
|
|
200
|
+
*/
|
|
201
|
+
resetConversation() {
|
|
202
|
+
this.cancelAll();
|
|
203
|
+
this.conversation = (0, core_1.createConversationSession)();
|
|
204
|
+
this.lastExchange = null;
|
|
205
|
+
void (0, core_1.clearPersistedConversation)(this.config.storage, this.config.manifest.appId, this.conversationScope, this.conversationIdentity);
|
|
206
|
+
this.emit();
|
|
155
207
|
}
|
|
156
208
|
// ── Subscription / state ───────────────────────────────────────────────────
|
|
157
209
|
getState() {
|
|
@@ -820,6 +872,9 @@ class AgentController {
|
|
|
820
872
|
this.setPhase('idle');
|
|
821
873
|
return;
|
|
822
874
|
}
|
|
875
|
+
// Identity gate: if the host user changed since the last turn (login,
|
|
876
|
+
// logout, account switch), swap conversations BEFORE recording anything.
|
|
877
|
+
this.syncConversationIdentity();
|
|
823
878
|
this.setPhase('thinking');
|
|
824
879
|
// REAL activity: the request is genuinely in flight from this moment.
|
|
825
880
|
this.setActivity({ kind: 'thinking' });
|
|
@@ -1112,6 +1167,8 @@ class AgentController {
|
|
|
1112
1167
|
}
|
|
1113
1168
|
dispose() {
|
|
1114
1169
|
this.cancelAll();
|
|
1170
|
+
this.removeIdentityListeners?.();
|
|
1171
|
+
this.removeIdentityListeners = null;
|
|
1115
1172
|
if (this.loadOlderTimer) {
|
|
1116
1173
|
clearTimeout(this.loadOlderTimer);
|
|
1117
1174
|
this.loadOlderTimer = null;
|
|
@@ -59,6 +59,11 @@ export interface FiodosAgentHandle {
|
|
|
59
59
|
orb: MountedOrb | null;
|
|
60
60
|
/** Resolves once the controller is ready (immediately on the manual path). */
|
|
61
61
|
ready: Promise<AgentController | null>;
|
|
62
|
+
/**
|
|
63
|
+
* Wipes the current identity's conversation (live memory + persisted blob).
|
|
64
|
+
* Call it from the app's logout for a hard wipe; no-op until ready.
|
|
65
|
+
*/
|
|
66
|
+
resetConversation(): void;
|
|
62
67
|
destroy(): void;
|
|
63
68
|
}
|
|
64
69
|
export declare function createFiodosAgent(options: CreateFiodosAgentOptions): FiodosAgentHandle;
|
|
@@ -75,6 +75,7 @@ function assemble(options, manifest, baseUrl) {
|
|
|
75
75
|
storage: (0, webStorageAdapter_1.createWebStorageAdapter)(),
|
|
76
76
|
telemetry,
|
|
77
77
|
isAuthenticated: options.isAuthenticated,
|
|
78
|
+
getUserId: options.getUserId,
|
|
78
79
|
ttsVoice: options.ttsVoice,
|
|
79
80
|
...options.configOverrides,
|
|
80
81
|
};
|
|
@@ -97,6 +98,9 @@ function createFiodosAgent(options) {
|
|
|
97
98
|
controller,
|
|
98
99
|
orb,
|
|
99
100
|
ready: Promise.resolve(controller),
|
|
101
|
+
resetConversation() {
|
|
102
|
+
controller.resetConversation();
|
|
103
|
+
},
|
|
100
104
|
destroy() {
|
|
101
105
|
orb?.unmount();
|
|
102
106
|
controller.dispose();
|
|
@@ -109,6 +113,9 @@ function createFiodosAgent(options) {
|
|
|
109
113
|
controller: null,
|
|
110
114
|
orb: null,
|
|
111
115
|
ready: Promise.resolve(null),
|
|
116
|
+
resetConversation() {
|
|
117
|
+
handle.controller?.resetConversation();
|
|
118
|
+
},
|
|
112
119
|
destroy() {
|
|
113
120
|
cancelled = true;
|
|
114
121
|
handle.orb?.unmount();
|
package/dist/cjs/version.d.ts
CHANGED
|
@@ -5,5 +5,5 @@
|
|
|
5
5
|
* Auto-generated by scripts/sync-sdk-version.mjs from package.json. Do not edit
|
|
6
6
|
* by hand — change package.json `version` and re-run the sync/release script.
|
|
7
7
|
*/
|
|
8
|
-
export declare const SDK_VERSION = "0.1.
|
|
8
|
+
export declare const SDK_VERSION = "0.1.12";
|
|
9
9
|
export declare const SDK_PACKAGE = "@fiodos/web-core";
|
package/dist/cjs/version.js
CHANGED
|
@@ -8,5 +8,5 @@ exports.SDK_PACKAGE = exports.SDK_VERSION = void 0;
|
|
|
8
8
|
* Auto-generated by scripts/sync-sdk-version.mjs from package.json. Do not edit
|
|
9
9
|
* by hand — change package.json `version` and re-run the sync/release script.
|
|
10
10
|
*/
|
|
11
|
-
exports.SDK_VERSION = '0.1.
|
|
11
|
+
exports.SDK_VERSION = '0.1.12';
|
|
12
12
|
exports.SDK_PACKAGE = '@fiodos/web-core';
|
|
@@ -56,6 +56,12 @@ export interface FiodosWebAgentConfig {
|
|
|
56
56
|
telemetry?: TelemetryAdapter;
|
|
57
57
|
/** Host auth check, required by manifest actions declaring requiresAuth. */
|
|
58
58
|
isAuthenticated?: () => boolean;
|
|
59
|
+
/**
|
|
60
|
+
* Host end-user identity. Conversation memory is namespaced per identity
|
|
61
|
+
* (hashed LOCALLY, never sent by this module): logout/account switches swap
|
|
62
|
+
* to that identity's own conversation instead of leaking the previous one.
|
|
63
|
+
*/
|
|
64
|
+
getUserId?: () => string | null;
|
|
59
65
|
messages?: {
|
|
60
66
|
catalogs?: Record<string, MessageCatalog>;
|
|
61
67
|
overrides?: Partial<AgentMessages>;
|
|
@@ -89,7 +89,7 @@ export declare class AgentController {
|
|
|
89
89
|
private consentModalVisible;
|
|
90
90
|
private readonly sessionId;
|
|
91
91
|
private sessionStarted;
|
|
92
|
-
private
|
|
92
|
+
private conversation;
|
|
93
93
|
private pending;
|
|
94
94
|
private confirmationReasked;
|
|
95
95
|
private confirmationVoiceActive;
|
|
@@ -116,6 +116,10 @@ export declare class AgentController {
|
|
|
116
116
|
/** Persistence scope: internal orbs keep their memory under a separate key
|
|
117
117
|
* so a public orb sharing the same appId can never read it. */
|
|
118
118
|
private conversationScope;
|
|
119
|
+
/** Current identity segment (LOCAL hash of the host's getUserId; never sent
|
|
120
|
+
* anywhere). The conversation belongs to (app, scope, identity). */
|
|
121
|
+
private conversationIdentity;
|
|
122
|
+
private removeIdentityListeners;
|
|
119
123
|
private loadingOlderExchanges;
|
|
120
124
|
private loadOlderTimer;
|
|
121
125
|
private readonly listeners;
|
|
@@ -123,6 +127,22 @@ export declare class AgentController {
|
|
|
123
127
|
constructor(config: FiodosWebAgentConfig);
|
|
124
128
|
private restorePersistedConversation;
|
|
125
129
|
private persistConversation;
|
|
130
|
+
/**
|
|
131
|
+
* Re-evaluates the host identity and, when it changed, swaps conversations:
|
|
132
|
+
* the outgoing identity's session is saved under ITS private key (so a user
|
|
133
|
+
* who logs back in recovers it, honouring "never clear"), all in-memory
|
|
134
|
+
* state and UI are wiped, and the incoming identity's own session (usually
|
|
135
|
+
* empty) is restored. An anonymous visitor after a logout always starts
|
|
136
|
+
* clean — the previous user's transcript is never inherited.
|
|
137
|
+
*/
|
|
138
|
+
private syncConversationIdentity;
|
|
139
|
+
/**
|
|
140
|
+
* Wipes the CURRENT identity's conversation: live memory, panel and the
|
|
141
|
+
* persisted blob. Hosts can call it from their logout for a hard wipe (by
|
|
142
|
+
* default a logout only parks the conversation under the user's private
|
|
143
|
+
* local key).
|
|
144
|
+
*/
|
|
145
|
+
resetConversation(): void;
|
|
126
146
|
getState(): AgentState;
|
|
127
147
|
/** Update the REAL live activity and re-render (no-op when unchanged). */
|
|
128
148
|
private setActivity;
|
|
@@ -15,7 +15,7 @@
|
|
|
15
15
|
* deliberate modal tap; a loose "yes" never confirms them.
|
|
16
16
|
* - The agent only ever executes actions declared in the manifest.
|
|
17
17
|
*/
|
|
18
|
-
import { combineContexts, createActionExecutor, createConsentManager, createSafeTelemetry, createSanitizer, buildBubbleExchangeWindow, BUBBLE_PAGE_EXCHANGES, conversationRetentionOptions, createConversationSession, persistConversationSession, restoreConversationSession, defaultRouteContextText, formatMessage, prepareConversationForTurn, recordConversationExchange, resolveConfirmationLexicon, resolveMessages, validateManifest, } from '@fiodos/core';
|
|
18
|
+
import { combineContexts, createActionExecutor, createConsentManager, createSafeTelemetry, createSanitizer, buildBubbleExchangeWindow, BUBBLE_PAGE_EXCHANGES, clearPersistedConversation, conversationIdentityKey, conversationRetentionOptions, createConversationSession, persistConversationSession, restoreConversationSession, defaultRouteContextText, formatMessage, prepareConversationForTurn, recordConversationExchange, resolveConfirmationLexicon, resolveMessages, validateManifest, } from '@fiodos/core';
|
|
19
19
|
import { AgentApiError } from '../api/errors.js';
|
|
20
20
|
import { formatAgentTurnError } from '../api/formatTurnError.js';
|
|
21
21
|
import { buildManifestPayload } from '../api/backendClient.js';
|
|
@@ -40,6 +40,7 @@ export class AgentController {
|
|
|
40
40
|
this.consentModalVisible = false;
|
|
41
41
|
this.sessionId = randomSessionId();
|
|
42
42
|
this.sessionStarted = false;
|
|
43
|
+
// Replaced wholesale on identity swaps / explicit resets.
|
|
43
44
|
this.conversation = createConversationSession();
|
|
44
45
|
this.pending = null;
|
|
45
46
|
this.confirmationReasked = false;
|
|
@@ -69,6 +70,7 @@ export class AgentController {
|
|
|
69
70
|
/** Persistence scope: internal orbs keep their memory under a separate key
|
|
70
71
|
* so a public orb sharing the same appId can never read it. */
|
|
71
72
|
this.conversationScope = 'public';
|
|
73
|
+
this.removeIdentityListeners = null;
|
|
72
74
|
this.loadingOlderExchanges = false;
|
|
73
75
|
this.loadOlderTimer = null;
|
|
74
76
|
this.listeners = new Set();
|
|
@@ -128,15 +130,29 @@ export class AgentController {
|
|
|
128
130
|
});
|
|
129
131
|
// Re-emit combined state whenever the speech machine advances.
|
|
130
132
|
this.unsubscribeSpeech = this.speech.subscribe(() => this.emit());
|
|
133
|
+
this.conversationIdentity = conversationIdentityKey(config.getUserId?.());
|
|
131
134
|
// Rehydrate the previous conversation (page reloads): the persisted blob
|
|
132
135
|
// carries its own retention rule, so expiry is decided correctly even
|
|
133
136
|
// before the published config arrives. Best-effort and non-blocking.
|
|
134
137
|
void this.restorePersistedConversation();
|
|
138
|
+
// Logout/login usually happens on another screen: re-check identity when
|
|
139
|
+
// the tab regains focus or becomes visible again, besides before every turn.
|
|
140
|
+
if (typeof window !== 'undefined') {
|
|
141
|
+
const check = () => void this.syncConversationIdentity();
|
|
142
|
+
window.addEventListener('focus', check);
|
|
143
|
+
document.addEventListener('visibilitychange', check);
|
|
144
|
+
this.removeIdentityListeners = () => {
|
|
145
|
+
window.removeEventListener('focus', check);
|
|
146
|
+
document.removeEventListener('visibilitychange', check);
|
|
147
|
+
};
|
|
148
|
+
}
|
|
135
149
|
}
|
|
136
150
|
// ── Conversation persistence (survives page reloads) ───────────────────────
|
|
137
151
|
async restorePersistedConversation() {
|
|
138
|
-
const
|
|
139
|
-
|
|
152
|
+
const identityAtStart = this.conversationIdentity;
|
|
153
|
+
const restored = await restoreConversationSession(this.config.storage, this.config.manifest.appId, Date.now(), this.conversationScope, identityAtStart);
|
|
154
|
+
// The identity may have changed again while the read resolved.
|
|
155
|
+
if (!restored || this.conversationIdentity !== identityAtStart)
|
|
140
156
|
return;
|
|
141
157
|
// Never clobber turns the user already made while the restore resolved.
|
|
142
158
|
if (this.conversation.turns.length > 0 || this.conversation.uiArchive?.length)
|
|
@@ -148,7 +164,43 @@ export class AgentController {
|
|
|
148
164
|
this.emit();
|
|
149
165
|
}
|
|
150
166
|
persistConversation() {
|
|
151
|
-
void persistConversationSession(this.config.storage, this.config.manifest.appId, this.conversation, this.conversationRetentionMinutes, this.conversationScope);
|
|
167
|
+
void persistConversationSession(this.config.storage, this.config.manifest.appId, this.conversation, this.conversationRetentionMinutes, this.conversationScope, this.conversationIdentity);
|
|
168
|
+
}
|
|
169
|
+
/**
|
|
170
|
+
* Re-evaluates the host identity and, when it changed, swaps conversations:
|
|
171
|
+
* the outgoing identity's session is saved under ITS private key (so a user
|
|
172
|
+
* who logs back in recovers it, honouring "never clear"), all in-memory
|
|
173
|
+
* state and UI are wiped, and the incoming identity's own session (usually
|
|
174
|
+
* empty) is restored. An anonymous visitor after a logout always starts
|
|
175
|
+
* clean — the previous user's transcript is never inherited.
|
|
176
|
+
*/
|
|
177
|
+
syncConversationIdentity() {
|
|
178
|
+
const next = conversationIdentityKey(this.config.getUserId?.());
|
|
179
|
+
if (next === this.conversationIdentity)
|
|
180
|
+
return false;
|
|
181
|
+
// 1. Park the outgoing identity's session under its own key.
|
|
182
|
+
this.persistConversation();
|
|
183
|
+
// 2. Wipe every trace from memory and the panel.
|
|
184
|
+
this.conversation = createConversationSession();
|
|
185
|
+
this.conversationIdentity = next;
|
|
186
|
+
this.lastExchange = null;
|
|
187
|
+
this.emit();
|
|
188
|
+
// 3. Bring in the new identity's own session, if any.
|
|
189
|
+
void this.restorePersistedConversation();
|
|
190
|
+
return true;
|
|
191
|
+
}
|
|
192
|
+
/**
|
|
193
|
+
* Wipes the CURRENT identity's conversation: live memory, panel and the
|
|
194
|
+
* persisted blob. Hosts can call it from their logout for a hard wipe (by
|
|
195
|
+
* default a logout only parks the conversation under the user's private
|
|
196
|
+
* local key).
|
|
197
|
+
*/
|
|
198
|
+
resetConversation() {
|
|
199
|
+
this.cancelAll();
|
|
200
|
+
this.conversation = createConversationSession();
|
|
201
|
+
this.lastExchange = null;
|
|
202
|
+
void clearPersistedConversation(this.config.storage, this.config.manifest.appId, this.conversationScope, this.conversationIdentity);
|
|
203
|
+
this.emit();
|
|
152
204
|
}
|
|
153
205
|
// ── Subscription / state ───────────────────────────────────────────────────
|
|
154
206
|
getState() {
|
|
@@ -817,6 +869,9 @@ export class AgentController {
|
|
|
817
869
|
this.setPhase('idle');
|
|
818
870
|
return;
|
|
819
871
|
}
|
|
872
|
+
// Identity gate: if the host user changed since the last turn (login,
|
|
873
|
+
// logout, account switch), swap conversations BEFORE recording anything.
|
|
874
|
+
this.syncConversationIdentity();
|
|
820
875
|
this.setPhase('thinking');
|
|
821
876
|
// REAL activity: the request is genuinely in flight from this moment.
|
|
822
877
|
this.setActivity({ kind: 'thinking' });
|
|
@@ -1109,6 +1164,8 @@ export class AgentController {
|
|
|
1109
1164
|
}
|
|
1110
1165
|
dispose() {
|
|
1111
1166
|
this.cancelAll();
|
|
1167
|
+
this.removeIdentityListeners?.();
|
|
1168
|
+
this.removeIdentityListeners = null;
|
|
1112
1169
|
if (this.loadOlderTimer) {
|
|
1113
1170
|
clearTimeout(this.loadOlderTimer);
|
|
1114
1171
|
this.loadOlderTimer = null;
|
|
@@ -59,6 +59,11 @@ export interface FiodosAgentHandle {
|
|
|
59
59
|
orb: MountedOrb | null;
|
|
60
60
|
/** Resolves once the controller is ready (immediately on the manual path). */
|
|
61
61
|
ready: Promise<AgentController | null>;
|
|
62
|
+
/**
|
|
63
|
+
* Wipes the current identity's conversation (live memory + persisted blob).
|
|
64
|
+
* Call it from the app's logout for a hard wipe; no-op until ready.
|
|
65
|
+
*/
|
|
66
|
+
resetConversation(): void;
|
|
62
67
|
destroy(): void;
|
|
63
68
|
}
|
|
64
69
|
export declare function createFiodosAgent(options: CreateFiodosAgentOptions): FiodosAgentHandle;
|
|
@@ -72,6 +72,7 @@ function assemble(options, manifest, baseUrl) {
|
|
|
72
72
|
storage: createWebStorageAdapter(),
|
|
73
73
|
telemetry,
|
|
74
74
|
isAuthenticated: options.isAuthenticated,
|
|
75
|
+
getUserId: options.getUserId,
|
|
75
76
|
ttsVoice: options.ttsVoice,
|
|
76
77
|
...options.configOverrides,
|
|
77
78
|
};
|
|
@@ -94,6 +95,9 @@ export function createFiodosAgent(options) {
|
|
|
94
95
|
controller,
|
|
95
96
|
orb,
|
|
96
97
|
ready: Promise.resolve(controller),
|
|
98
|
+
resetConversation() {
|
|
99
|
+
controller.resetConversation();
|
|
100
|
+
},
|
|
97
101
|
destroy() {
|
|
98
102
|
orb?.unmount();
|
|
99
103
|
controller.dispose();
|
|
@@ -106,6 +110,9 @@ export function createFiodosAgent(options) {
|
|
|
106
110
|
controller: null,
|
|
107
111
|
orb: null,
|
|
108
112
|
ready: Promise.resolve(null),
|
|
113
|
+
resetConversation() {
|
|
114
|
+
handle.controller?.resetConversation();
|
|
115
|
+
},
|
|
109
116
|
destroy() {
|
|
110
117
|
cancelled = true;
|
|
111
118
|
handle.orb?.unmount();
|
package/dist/esm/version.d.ts
CHANGED
|
@@ -5,5 +5,5 @@
|
|
|
5
5
|
* Auto-generated by scripts/sync-sdk-version.mjs from package.json. Do not edit
|
|
6
6
|
* by hand — change package.json `version` and re-run the sync/release script.
|
|
7
7
|
*/
|
|
8
|
-
export declare const SDK_VERSION = "0.1.
|
|
8
|
+
export declare const SDK_VERSION = "0.1.12";
|
|
9
9
|
export declare const SDK_PACKAGE = "@fiodos/web-core";
|
package/dist/esm/version.js
CHANGED
|
@@ -5,5 +5,5 @@
|
|
|
5
5
|
* Auto-generated by scripts/sync-sdk-version.mjs from package.json. Do not edit
|
|
6
6
|
* by hand — change package.json `version` and re-run the sync/release script.
|
|
7
7
|
*/
|
|
8
|
-
export const SDK_VERSION = '0.1.
|
|
8
|
+
export const SDK_VERSION = '0.1.12';
|
|
9
9
|
export const SDK_PACKAGE = '@fiodos/web-core';
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@fiodos/web-core",
|
|
3
|
-
"version": "0.1.
|
|
3
|
+
"version": "0.1.12",
|
|
4
4
|
"description": "Framework-agnostic browser layer for the Fiodos agent: a vanilla AgentController (orchestrator), DOM adapters (navigation/voice/storage), HTTP client and decision engine over @fiodos/core. Shared base for @fiodos/vue, @fiodos/svelte and @fiodos/angular (no framework imports).",
|
|
5
5
|
"license": "SEE LICENSE IN LICENSE",
|
|
6
6
|
"publishConfig": {
|
|
@@ -29,7 +29,7 @@
|
|
|
29
29
|
"prepublishOnly": "node ../../scripts/sync-sdk-version.mjs && npm run build"
|
|
30
30
|
},
|
|
31
31
|
"dependencies": {
|
|
32
|
-
"@fiodos/core": "^0.1.
|
|
32
|
+
"@fiodos/core": "^0.1.9"
|
|
33
33
|
},
|
|
34
34
|
"devDependencies": {
|
|
35
35
|
"@types/node": "^22.0.0",
|