@dropout-ai/runtime 0.4.3 → 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 +55 -0
- package/package.json +1 -1
- package/src/index.d.ts +15 -0
- package/src/index.js +34 -40
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
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
|
@@ -69,7 +69,7 @@ class Dropout {
|
|
|
69
69
|
this.apiKey = config.apiKey;
|
|
70
70
|
this.debug = config.debug || false;
|
|
71
71
|
this.privacy = config.privacy || 'full';
|
|
72
|
-
this.captureEndpoint = SUPABASE_FUNCTION_URL;
|
|
72
|
+
this.captureEndpoint = config.captureEndpoint || SUPABASE_FUNCTION_URL;
|
|
73
73
|
this.maxOutputBytes = 32768;
|
|
74
74
|
|
|
75
75
|
// State
|
|
@@ -86,10 +86,10 @@ class Dropout {
|
|
|
86
86
|
}
|
|
87
87
|
global.__dropout_initialized__ = true;
|
|
88
88
|
|
|
89
|
-
// Identity
|
|
90
|
-
|
|
91
|
-
|
|
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) {
|
|
@@ -103,9 +103,6 @@ class Dropout {
|
|
|
103
103
|
// 4. Start Network Interceptor
|
|
104
104
|
this.patchNetwork();
|
|
105
105
|
|
|
106
|
-
// 5. SEND STARTUP PING
|
|
107
|
-
//this.sendStartupSignal();
|
|
108
|
-
|
|
109
106
|
// Lock the instance
|
|
110
107
|
Dropout.instance = this;
|
|
111
108
|
|
|
@@ -128,33 +125,23 @@ class Dropout {
|
|
|
128
125
|
}
|
|
129
126
|
}
|
|
130
127
|
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
method: 'POST',
|
|
149
|
-
headers: {
|
|
150
|
-
'Content-Type': 'application/json',
|
|
151
|
-
'x-dropout-key': this.apiKey
|
|
152
|
-
}
|
|
153
|
-
});
|
|
154
|
-
|
|
155
|
-
req.on('error', (e) => this.log("❌ Startup Signal Failed", e.message));
|
|
156
|
-
req.write(payload);
|
|
157
|
-
req.end();
|
|
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;
|
|
158
145
|
}
|
|
159
146
|
|
|
160
147
|
hash(text) {
|
|
@@ -208,6 +195,8 @@ class Dropout {
|
|
|
208
195
|
session_id: payload.session_id,
|
|
209
196
|
turn_index: payload.turn_index,
|
|
210
197
|
turn_role: payload.turn_role,
|
|
198
|
+
// ✅ DIRECTION LOGIC APPLIED HERE
|
|
199
|
+
direction: payload.turn_role === 'user' ? 'user_to_ai' : 'ai_to_user',
|
|
211
200
|
provider: payload.provider,
|
|
212
201
|
model: payload.model,
|
|
213
202
|
latency_ms: payload.latency_ms || null,
|
|
@@ -219,7 +208,10 @@ class Dropout {
|
|
|
219
208
|
|
|
220
209
|
this.log(`🚀 Sending Capture [${payload.turn_role}]`);
|
|
221
210
|
|
|
222
|
-
const
|
|
211
|
+
const isHttp = this.captureEndpoint.startsWith('http:');
|
|
212
|
+
const requestModule = isHttp ? http : https;
|
|
213
|
+
|
|
214
|
+
const req = requestModule.request(this.captureEndpoint, {
|
|
223
215
|
method: 'POST',
|
|
224
216
|
headers: {
|
|
225
217
|
'Content-Type': 'application/json',
|
|
@@ -270,7 +262,7 @@ class Dropout {
|
|
|
270
262
|
const pHash = _this.hash(bodyStr);
|
|
271
263
|
|
|
272
264
|
_this.emit({
|
|
273
|
-
session_id:
|
|
265
|
+
session_id: _this.currentSessionId,
|
|
274
266
|
turn_index: activeTurn,
|
|
275
267
|
turn_role: 'user',
|
|
276
268
|
provider,
|
|
@@ -295,7 +287,7 @@ class Dropout {
|
|
|
295
287
|
const oHash = _this.hash(oText);
|
|
296
288
|
|
|
297
289
|
_this.emit({
|
|
298
|
-
session_id:
|
|
290
|
+
session_id: _this.currentSessionId,
|
|
299
291
|
turn_index: activeTurn,
|
|
300
292
|
turn_role: 'assistant',
|
|
301
293
|
latency_ms: latency,
|
|
@@ -381,7 +373,7 @@ class Dropout {
|
|
|
381
373
|
clientRequest._dropout_model = model;
|
|
382
374
|
|
|
383
375
|
_this.emit({
|
|
384
|
-
session_id:
|
|
376
|
+
session_id: _this.currentSessionId,
|
|
385
377
|
turn_index: activeTurn,
|
|
386
378
|
turn_role: 'user',
|
|
387
379
|
provider,
|
|
@@ -408,7 +400,7 @@ class Dropout {
|
|
|
408
400
|
const oHash = _this.hash(resBody);
|
|
409
401
|
|
|
410
402
|
_this.emit({
|
|
411
|
-
session_id:
|
|
403
|
+
session_id: _this.currentSessionId,
|
|
412
404
|
turn_index: clientRequest._dropout_turn || 0,
|
|
413
405
|
turn_role: 'assistant',
|
|
414
406
|
latency_ms: latency,
|
|
@@ -444,4 +436,6 @@ if (typeof process !== 'undefined' && process.env.DROPOUT_PROJECT_ID && process.
|
|
|
444
436
|
});
|
|
445
437
|
}
|
|
446
438
|
|
|
439
|
+
// 🛡️ DUAL EXPORT FIX (Crucial for TypeScript + Require compatibility)
|
|
440
|
+
Dropout.default = Dropout;
|
|
447
441
|
module.exports = Dropout;
|