@dropout-ai/runtime 0.4.4 → 0.4.5

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/README.md CHANGED
@@ -115,6 +115,61 @@ bootstrap();
115
115
  | `apiKey` | `string` | Your Secret Key (`dp_live_...`). | ✅ |
116
116
  | `debug` | `boolean` | Set `true` to see "🟢 Online" logs and errors in console. | No |
117
117
  | `privacy` | `string` | `full` (capture text) or `mask` (metadata only). Default: `full`. | No |
118
+ | `sessionId` | `string` | Optional initial session ID. If not provided, one is generated. | No |
119
+ | `captureEndpoint` | `string` | Custom capture endpoint (for testing). Default: production URL. | No |
120
+
121
+ ---
122
+
123
+ ## 🔑 Session Management
124
+
125
+ **Important:** A **session** represents a single conversation thread. By default, Dropout generates one session ID when initialized and uses it for all interactions. For proper analytics, you should call `startNewSession()` whenever the user starts a new conversation.
126
+
127
+ ### When to Call `startNewSession()`
128
+
129
+ Call this method when:
130
+ - User clicks "New Chat" button
131
+ - User switches to a different conversation thread
132
+ - User switches AI models (if you want to treat that as a new conversation)
133
+ - Page refreshes and you want to start a fresh session
134
+
135
+ ### Example Usage
136
+
137
+ ```javascript
138
+ const Dropout = require('@dropout-ai/runtime');
139
+
140
+ // Initialize once at app startup
141
+ const dropout = Dropout.init({
142
+ apiKey: process.env.DROPOUT_API_KEY,
143
+ projectId: process.env.DROPOUT_PROJECT_ID
144
+ });
145
+
146
+ // Later, when user clicks "New Chat":
147
+ app.post('/api/new-chat', (req, res) => {
148
+ const newSessionId = dropout.startNewSession();
149
+ console.log(`Started new session: ${newSessionId}`);
150
+ res.json({ sessionId: newSessionId });
151
+ });
152
+
153
+ // Or with a custom session ID:
154
+ dropout.startNewSession('user_123_chat_456');
155
+ ```
156
+
157
+ ### TypeScript Example
158
+
159
+ ```typescript
160
+ import Dropout from '@dropout-ai/runtime';
161
+
162
+ const dropout = Dropout.init({
163
+ apiKey: process.env.DROPOUT_API_KEY!,
164
+ projectId: process.env.DROPOUT_PROJECT_ID!
165
+ });
166
+
167
+ // Access current session
168
+ console.log(dropout.currentSessionId);
169
+
170
+ // Start new session
171
+ const newSessionId = dropout.startNewSession();
172
+ ```
118
173
 
119
174
  ---
120
175
 
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@dropout-ai/runtime",
3
- "version": "0.4.4",
3
+ "version": "0.4.5",
4
4
  "description": "Invisible Node.js runtime for understanding behavioral impact of AI interactions.",
5
5
  "main": "src/index.js",
6
6
  "types": "src/index.d.ts",
package/src/index.d.ts CHANGED
@@ -5,6 +5,8 @@ export interface DropoutConfig {
5
5
  apiKey: string;
6
6
  debug?: boolean;
7
7
  privacy?: 'full' | 'mask';
8
+ sessionId?: string;
9
+ captureEndpoint?: string;
8
10
  }
9
11
 
10
12
  export default class Dropout {
@@ -28,11 +30,24 @@ export default class Dropout {
28
30
  */
29
31
  privacy: 'full' | 'mask';
30
32
 
33
+ /**
34
+ * Current session ID for tracking conversation threads.
35
+ */
36
+ currentSessionId: string;
37
+
31
38
  /**
32
39
  * Universal Initialization Method (Idempotent).
33
40
  * Safe to call multiple times; will only initialize once.
34
41
  */
35
42
  static init(config: DropoutConfig): Dropout;
36
43
 
44
+ /**
45
+ * Start a new session (e.g., when user clicks "New Chat").
46
+ * Resets turn counter and generates a fresh session ID.
47
+ * @param customSessionId - Optional custom session ID, otherwise auto-generates
48
+ * @returns The new session ID
49
+ */
50
+ startNewSession(customSessionId?: string): string;
51
+
37
52
  constructor(config: DropoutConfig);
38
53
  }
package/src/index.js CHANGED
@@ -86,10 +86,10 @@ class Dropout {
86
86
  }
87
87
  global.__dropout_initialized__ = true;
88
88
 
89
- // Identity
90
- if (!global.__dropout_session_id__) {
91
- global.__dropout_session_id__ = this.generateSessionId();
92
- }
89
+ // ✅ Session Identity (Instance-Level, Not Global)
90
+ // Accept session_id from config OR generate a default
91
+ // Host app controls session lifecycle via startNewSession()
92
+ this.currentSessionId = config.sessionId || this.generateSessionId();
93
93
 
94
94
  // ✅ VISUAL SUCCESS INDICATOR
95
95
  if (this.debug) {
@@ -125,6 +125,25 @@ class Dropout {
125
125
  }
126
126
  }
127
127
 
128
+ /**
129
+ * 🔑 START NEW SESSION
130
+ * Call this when user clicks "New Chat" or starts a new conversation thread.
131
+ * Resets turn counter and generates a fresh session_id.
132
+ * @param {string} [customSessionId] - Optional custom session ID, otherwise auto-generates
133
+ * @returns {string} The new session ID
134
+ */
135
+ startNewSession(customSessionId) {
136
+ this.currentSessionId = customSessionId || this.generateSessionId();
137
+ this.turnIndex = 0; // Reset turn counter for new session
138
+ this.lastTurnConfirmed = true;
139
+ this.lastPromptHash = null;
140
+ this.lastResponseHash = null;
141
+ if (this.debug) {
142
+ console.log(`[Dropout] 🔄 New Session Started: ${this.currentSessionId}`);
143
+ }
144
+ return this.currentSessionId;
145
+ }
146
+
128
147
  hash(text) {
129
148
  if (!text) return null;
130
149
  try {
@@ -243,7 +262,7 @@ class Dropout {
243
262
  const pHash = _this.hash(bodyStr);
244
263
 
245
264
  _this.emit({
246
- session_id: global.__dropout_session_id__,
265
+ session_id: _this.currentSessionId,
247
266
  turn_index: activeTurn,
248
267
  turn_role: 'user',
249
268
  provider,
@@ -268,7 +287,7 @@ class Dropout {
268
287
  const oHash = _this.hash(oText);
269
288
 
270
289
  _this.emit({
271
- session_id: global.__dropout_session_id__,
290
+ session_id: _this.currentSessionId,
272
291
  turn_index: activeTurn,
273
292
  turn_role: 'assistant',
274
293
  latency_ms: latency,
@@ -354,7 +373,7 @@ class Dropout {
354
373
  clientRequest._dropout_model = model;
355
374
 
356
375
  _this.emit({
357
- session_id: global.__dropout_session_id__,
376
+ session_id: _this.currentSessionId,
358
377
  turn_index: activeTurn,
359
378
  turn_role: 'user',
360
379
  provider,
@@ -381,7 +400,7 @@ class Dropout {
381
400
  const oHash = _this.hash(resBody);
382
401
 
383
402
  _this.emit({
384
- session_id: global.__dropout_session_id__,
403
+ session_id: _this.currentSessionId,
385
404
  turn_index: clientRequest._dropout_turn || 0,
386
405
  turn_role: 'assistant',
387
406
  latency_ms: latency,