Martechsol commited on
Commit
e441398
Β·
1 Parent(s): afb4b4d

feat: pre-create named session on widget load via /api/session/init

Browse files
Files changed (3) hide show
  1. app/api/schemas.py +5 -0
  2. app/main.py +25 -1
  3. static/addon.html +22 -17
app/api/schemas.py CHANGED
@@ -25,3 +25,8 @@ class HealthResponse(BaseModel):
25
  class SessionUpdateNameRequest(BaseModel):
26
  session_id: str
27
  user_name: str
 
 
 
 
 
 
25
  class SessionUpdateNameRequest(BaseModel):
26
  session_id: str
27
  user_name: str
28
+
29
+
30
+ class SessionInitRequest(BaseModel):
31
+ session_id: str
32
+ user_name: str | None = Field(default=None, description="User name to associate with the session at creation time")
app/main.py CHANGED
@@ -6,7 +6,7 @@ from fastapi.middleware.cors import CORSMiddleware
6
  from fastapi.staticfiles import StaticFiles
7
  import os
8
 
9
- from app.api.schemas import ChatRequest, ChatResponse, HealthResponse, SessionUpdateNameRequest
10
  from app.core.config import get_settings
11
  from app.services.embeddings import EmbeddingService
12
  from app.services.llm import LLMService
@@ -193,6 +193,30 @@ async def update_session_user_name(payload: SessionUpdateNameRequest):
193
  return {"status": "ok", "new_session_id": new_id}
194
 
195
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
196
  @fastapi_app.get("/api/session/history/{session_id}")
197
  async def get_session_history(session_id: str):
198
  """Returns the chat history for a session formatted for the frontend."""
 
6
  from fastapi.staticfiles import StaticFiles
7
  import os
8
 
9
+ from app.api.schemas import ChatRequest, ChatResponse, HealthResponse, SessionUpdateNameRequest, SessionInitRequest
10
  from app.core.config import get_settings
11
  from app.services.embeddings import EmbeddingService
12
  from app.services.llm import LLMService
 
193
  return {"status": "ok", "new_session_id": new_id}
194
 
195
 
196
+ @fastapi_app.post("/api/session/init")
197
+ async def init_session(payload: SessionInitRequest):
198
+ """
199
+ Pre-creates a session on widget load β€” before the user opens the chat.
200
+ If user_name is provided the session is immediately renamed to the canonical
201
+ named session (merging any existing temp session). The caller should store
202
+ the returned session_id in localStorage so subsequent requests use the same ID.
203
+ """
204
+ import re
205
+
206
+ # Ensure the temp session file exists first
207
+ await _ss.ensure_session(payload.session_id)
208
+
209
+ if payload.user_name and payload.user_name.strip():
210
+ # Immediately promote to named session
211
+ clean_name = re.sub(r'[^\w\s-]', '', payload.user_name).strip().replace(' ', '_')
212
+ new_id = await _ss.rename_session(payload.session_id, payload.user_name)
213
+ logger.info("session/init: pre-created named session '%s' for user '%s'", new_id, payload.user_name)
214
+ return {"status": "ok", "session_id": new_id}
215
+ else:
216
+ logger.info("session/init: pre-created temp session '%s' (name unknown yet)", payload.session_id)
217
+ return {"status": "ok", "session_id": payload.session_id}
218
+
219
+
220
  @fastapi_app.get("/api/session/history/{session_id}")
221
  async def get_session_history(session_id: str):
222
  """Returns the chat history for a session formatted for the frontend."""
static/addon.html CHANGED
@@ -425,20 +425,23 @@
425
  localStorage.setItem('martech_last_user_name', userName);
426
  }
427
 
428
- // Sync name with backend FIRST β†’ get the real session ID before fetching history
429
- // (Bug fix: previously history was fetched before session ID was finalized)
430
- if (userName) {
431
- try {
432
- const rData = await fetch(BASE_URL + "/api/session/update-name", {
433
- method: 'POST',
434
- headers: { 'Content-Type': 'application/json' },
435
- body: JSON.stringify({ session_id: sessionId, user_name: userName })
436
- }).then(r => r.json());
437
- if (rData.new_session_id && rData.new_session_id !== sessionId) {
438
- sessionId = rData.new_session_id;
439
- localStorage.setItem('martech_session_id', sessionId);
440
- }
441
- } catch (e) {}
 
 
 
442
  }
443
 
444
  // Now fetch history using the finalized session ID
@@ -457,6 +460,7 @@
457
  } catch (e) {}
458
 
459
  // If name still not found, set up continuous lightweight background resolution
 
460
  if (!userName) {
461
  let _isResolving = false;
462
 
@@ -469,13 +473,14 @@
469
  if (resolved) {
470
  localStorage.setItem('martech_last_user_name', resolved);
471
  try {
472
- const rData = await fetch(BASE_URL + "/api/session/update-name", {
 
473
  method: 'POST',
474
  headers: { 'Content-Type': 'application/json' },
475
  body: JSON.stringify({ session_id: sessionId, user_name: resolved })
476
  }).then(r => r.json());
477
- if (rData.new_session_id && rData.new_session_id !== sessionId) {
478
- sessionId = rData.new_session_id;
479
  localStorage.setItem('martech_session_id', sessionId);
480
  }
481
  } catch (e) {}
 
425
  localStorage.setItem('martech_last_user_name', userName);
426
  }
427
 
428
+ // ── PRE-CREATE SESSION AT BACKEND ON WIDGET LOAD ────────────────────
429
+ // This creates the session with the user's name BEFORE the user even
430
+ // opens the chat window, so it is immediately visible in the admin panel.
431
+ try {
432
+ const initData = await fetch(BASE_URL + "/api/session/init", {
433
+ method: 'POST',
434
+ headers: { 'Content-Type': 'application/json' },
435
+ body: JSON.stringify({ session_id: sessionId, user_name: userName || null })
436
+ }).then(r => r.json());
437
+ // Backend may return a canonical named session_id (e.g. "Ali_Hassan")
438
+ if (initData.session_id && initData.session_id !== sessionId) {
439
+ sessionId = initData.session_id;
440
+ localStorage.setItem('martech_session_id', sessionId);
441
+ }
442
+ } catch (e) {
443
+ // Non-fatal: session will still be created on first message if this fails
444
+ console.warn('Martech: background session pre-creation failed', e);
445
  }
446
 
447
  // Now fetch history using the finalized session ID
 
460
  } catch (e) {}
461
 
462
  // If name still not found, set up continuous lightweight background resolution
463
+ // so the session gets named as soon as auth is available
464
  if (!userName) {
465
  let _isResolving = false;
466
 
 
473
  if (resolved) {
474
  localStorage.setItem('martech_last_user_name', resolved);
475
  try {
476
+ // Re-init with the now-known name to promote temp β†’ named session
477
+ const rData = await fetch(BASE_URL + "/api/session/init", {
478
  method: 'POST',
479
  headers: { 'Content-Type': 'application/json' },
480
  body: JSON.stringify({ session_id: sessionId, user_name: resolved })
481
  }).then(r => r.json());
482
+ if (rData.session_id && rData.session_id !== sessionId) {
483
+ sessionId = rData.session_id;
484
  localStorage.setItem('martech_session_id', sessionId);
485
  }
486
  } catch (e) {}