@dropout-ai/runtime 0.3.8 → 0.3.9

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.
Files changed (2) hide show
  1. package/package.json +1 -1
  2. package/src/index.js +61 -82
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@dropout-ai/runtime",
3
- "version": "0.3.8",
3
+ "version": "0.3.9",
4
4
  "description": "Invisible Node.js runtime for capturing AI interactions.",
5
5
  "main": "src/index.js",
6
6
  "scripts": {
package/src/index.js CHANGED
@@ -1,13 +1,14 @@
1
1
  /**
2
2
  * @dropout-ai/runtime
3
3
  * Universal AI Interaction Capture for Node.js
4
- * Stability: High (Browser-Safe, Silent Failures)
5
- * Features: Auto-Discovery, Connectivity Check, Dual-Schema Support
4
+ * Feature: Always-On Heartbeat & Auto-Discovery
6
5
  */
7
6
 
8
- let https, http, crypto;
7
+ const https = require('https');
8
+ const http = require('http');
9
+ const crypto = require('crypto');
9
10
 
10
- // --- DEFAULT CONFIGURATION ---
11
+ // --- CONFIGURATION ---
11
12
  const SUPABASE_FUNCTION_URL = "https://hipughmjlwmwjxzyxfzs.supabase.co/functions/v1/capture-sealed";
12
13
 
13
14
  // Known AI Domains
@@ -18,74 +19,53 @@ const KNOWN_AI_DOMAINS = [
18
19
 
19
20
  class Dropout {
20
21
  constructor(config = {}) {
21
- // đŸ›Ąī¸ 1. BROWSER GUARD (Client-Side Protection)
22
- // If this accidentally runs in a browser/Client Component, we abort silently.
22
+ // đŸ›Ąī¸ BROWSER GUARD
23
23
  if (typeof window !== 'undefined' && typeof window.document !== 'undefined') {
24
- if (config.debug) console.warn("[Dropout] âš ī¸ Skipped: Browser detected. SDK is Server-Only.");
24
+ if (config.debug) console.warn("[Dropout] âš ī¸ Skipped: Browser detected.");
25
25
  return;
26
26
  }
27
27
 
28
- // đŸ›Ąī¸ 2. CREDENTIAL CHECK
28
+ // đŸ›Ąī¸ CREDENTIAL GUARD
29
29
  if (!config.apiKey || !config.projectId) {
30
- if (config.debug) console.warn("[Dropout] âš ī¸ Skipped: Missing API Key or Project ID.");
30
+ if (config.debug) console.warn("[Dropout] âš ī¸ Skipped: Missing Credentials.");
31
31
  return;
32
32
  }
33
33
 
34
- // đŸ›Ąī¸ 3. DEPENDENCY CHECK
35
- try {
36
- https = require('https');
37
- http = require('http');
38
- crypto = require('crypto');
39
- } catch (e) {
40
- if (config.debug) console.warn("[Dropout] âš ī¸ Skipped: Node core modules missing.");
41
- return;
34
+ // Initialize
35
+ this.config = config;
36
+ this.projectId = config.projectId;
37
+ this.apiKey = config.apiKey;
38
+ this.debug = config.debug || false;
39
+ this.privacy = config.privacy || 'full';
40
+ this.captureEndpoint = SUPABASE_FUNCTION_URL;
41
+ this.maxOutputBytes = 32768;
42
+
43
+ // State
44
+ this.turnIndex = 0;
45
+ this.lastTurnConfirmed = true;
46
+ this.lastPromptHash = null;
47
+ this.lastResponseHash = null;
48
+
49
+ // Singleton Guard
50
+ if (global.__dropout_initialized__) return;
51
+ global.__dropout_initialized__ = true;
52
+
53
+ if (!global.__dropout_session_id__) {
54
+ global.__dropout_session_id__ = this.generateSessionId();
42
55
  }
43
56
 
44
- // --- INITIALIZATION ---
45
- try {
46
- this.config = config;
47
- this.projectId = config.projectId;
48
- this.apiKey = config.apiKey;
49
- this.debug = config.debug || false;
50
- this.privacy = config.privacy || 'full';
51
- this.captureEndpoint = SUPABASE_FUNCTION_URL;
52
- this.maxOutputBytes = 32768;
53
-
54
- // State
55
- this.turnIndex = 0;
56
- this.lastTurnConfirmed = true;
57
- this.lastPromptHash = null;
58
- this.lastResponseHash = null;
59
-
60
- // Singleton Guard
61
- if (global.__dropout_initialized__) {
62
- if (this.debug) console.log("[Dropout] â„šī¸ Already initialized.");
63
- return;
64
- }
65
- global.__dropout_initialized__ = true;
66
-
67
- // Identity
68
- if (!global.__dropout_session_id__) {
69
- global.__dropout_session_id__ = this.generateSessionId();
70
- }
57
+ if (this.debug) console.log(`[Dropout] đŸŸĸ Online: ${this.projectId}`);
71
58
 
72
- // Bindings
73
- this.log = this.log.bind(this);
74
- this.emit = this.emit.bind(this);
59
+ // Bindings
60
+ this.log = this.log.bind(this);
61
+ this.emit = this.emit.bind(this);
75
62
 
76
- // đŸ›Ąī¸ 4. SAFE STARTUP
77
- this.patchNetwork();
63
+ // 1. Start Network Interceptor
64
+ this.patchNetwork();
78
65
 
79
- // 🔍 5. CONNECTION VERIFICATION (Async Ping)
80
- // Only runs if debug is TRUE to confirm setup
81
- if (this.debug) {
82
- this.validateConnection();
83
- }
84
-
85
- } catch (err) {
86
- // THE ULTIMATE CATCH-ALL: Ensure app NEVER crashes
87
- if (config.debug) console.error("[Dropout] ❌ Initialization Error:", err);
88
- }
66
+ // 2. SEND STARTUP PING (Always run this, silent by default)
67
+ // This turns the dashboard status GREEN immediately on app boot.
68
+ this.sendStartupSignal();
89
69
  }
90
70
 
91
71
  // --- UTILS ---
@@ -101,9 +81,24 @@ class Dropout {
101
81
  }
102
82
  }
103
83
 
104
- // --- HEALTH CHECK ---
105
- validateConnection() {
106
- this.log("🔄 Verifying connection to Dropout Cloud...");
84
+ // --- HEARTBEAT ---
85
+ sendStartupSignal() {
86
+ // We send a discrete 'system_boot' event.
87
+ // The Database Trigger will see this and update projects.last_active_at
88
+ const payload = JSON.stringify({
89
+ project_id: this.projectId,
90
+ session_id: 'system_boot_' + Date.now(),
91
+ turn_role: 'system',
92
+ turn_index: 0,
93
+ content: 'Dropout SDK Initialized',
94
+ //content_blob: 'Dropout SDK Initialized',
95
+ metadata_flags: {
96
+ type: 'system_boot',
97
+ environment: process.env.NODE_ENV || 'development',
98
+ runtime: 'node'
99
+ },
100
+ received_at: new Date().toISOString()
101
+ });
107
102
 
108
103
  const req = https.request(this.captureEndpoint, {
109
104
  method: 'POST',
@@ -111,26 +106,11 @@ class Dropout {
111
106
  'Content-Type': 'application/json',
112
107
  'x-dropout-key': this.apiKey
113
108
  }
114
- }, (res) => {
115
- if (res.statusCode >= 200 && res.statusCode < 300) {
116
- console.log(`[Dropout] ✅ Connected to Project: ${this.projectId}`);
117
- } else {
118
- console.warn(`[Dropout] âš ī¸ Connection Failed (Status: ${res.statusCode}). Check your API Key.`);
119
- }
120
109
  });
121
110
 
122
- req.on('error', (e) => console.warn(`[Dropout] ❌ Connection Error: ${e.message}`));
123
-
124
- // Send lightweight Ping payload
125
- req.write(JSON.stringify({
126
- project_id: this.projectId,
127
- session_id: 'system_ping',
128
- turn_role: 'system',
129
- turn_index: 0,
130
- content: 'ping',
131
- //content_blob: 'ping',
132
- metadata_flags: { type: 'connectivity_check' }
133
- }));
111
+ // Silent error handling (unless debug is on)
112
+ req.on('error', (e) => this.log("❌ Startup Signal Failed", e.message));
113
+ req.write(payload);
134
114
  req.end();
135
115
  }
136
116
 
@@ -160,7 +140,7 @@ class Dropout {
160
140
  if (parsed.model) model = parsed.model;
161
141
  if (provider === 'custom' && (parsed.messages || parsed.prompt)) provider = 'heuristic';
162
142
  }
163
- } catch (e) { /* Ignore parsing errors */ }
143
+ } catch (e) { }
164
144
  return { provider, model };
165
145
  }
166
146
 
@@ -413,7 +393,6 @@ class Dropout {
413
393
  }
414
394
  }
415
395
 
416
- // Auto-Start (Server-Side Only)
417
396
  if (typeof process !== 'undefined' && process.env.DROPOUT_PROJECT_ID && process.env.DROPOUT_API_KEY) {
418
397
  new Dropout({
419
398
  projectId: process.env.DROPOUT_PROJECT_ID,