@dropout-ai/runtime 0.2.11 → 0.2.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.
Files changed (2) hide show
  1. package/package.json +1 -1
  2. package/src/index.js +22 -25
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@dropout-ai/runtime",
3
- "version": "0.2.11",
3
+ "version": "0.2.12",
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,16 @@
1
1
  /**
2
2
  * @dropout-ai/runtime
3
- * Role: Passive observer inside the user’s app.
4
- *
5
- * Runtime never reasons, never interprets, never stores intelligence.
6
- * it only: Observes, Normalizes, Emits signals.
3
+ * Role: Passive observer.
4
+ * Behavior: Fire-and-forget raw JSON to Supabase.
5
+ * Authentication: None (Public Endpoint).
7
6
  */
8
7
 
9
8
  const crypto = require('crypto');
10
9
 
10
+ // --- CONFIGURATION ---
11
+ // Public ingestion endpoint (No keys required)
12
+ const SUPABASE_FUNCTION_URL = "https://hipughmjlwmwjxzyxfzs.supabase.co/functions/v1/capture-sealed";
13
+
11
14
  // --- Identity & State ---
12
15
  const GLOBAL_OBJ = typeof window !== 'undefined' ? window : global;
13
16
 
@@ -28,29 +31,12 @@ let lastTurnConfirmed = true;
28
31
  let lastPromptHash = null;
29
32
  let lastResponseHash = null;
30
33
 
31
- const SUPABASE_FUNCTION_URL = "https://hipughmjlwmwjxzyxfzs.supabase.co/functions/v1/capture-sealed";
32
-
33
- // --- Runtime Guarantees ---
34
34
  let config = {
35
35
  maxOutputBytes: 32768,
36
36
  captureEndpoint: SUPABASE_FUNCTION_URL,
37
- configEndpoint: 'http://localhost:4000/config',
38
- privacyMode: (typeof process !== 'undefined' && process.env.DROPOUT_PRIVACY_MODE) || 'safe'
37
+ privacyMode: (typeof process !== 'undefined' && process.env.DROPOUT_PRIVACY_MODE) || 'full'
39
38
  };
40
39
 
41
- // Remote config fetch (Non-blocking)
42
- setTimeout(async () => {
43
- const fetchFn = GLOBAL_OBJ.__dropout_original_fetch__ || GLOBAL_OBJ.fetch;
44
- if (typeof fetchFn !== 'function') return;
45
- try {
46
- const resp = await fetchFn(config.configEndpoint);
47
- const remote = await resp.json();
48
- if (remote && typeof remote === 'object') {
49
- config = Object.assign(config, remote);
50
- }
51
- } catch (e) { }
52
- }, 0);
53
-
54
40
  /**
55
41
  * Telemetry Emitter (Non-blocking, Fire-and-forget)
56
42
  */
@@ -61,10 +47,15 @@ function emit(payload) {
61
47
  setTimeout(() => {
62
48
  fetchFn(config.captureEndpoint, {
63
49
  method: 'POST',
64
- headers: { 'Content-Type': 'application/json' },
50
+ headers: {
51
+ 'Content-Type': 'application/json'
52
+ // No Authorization header needed since Enforce JWT is OFF
53
+ },
65
54
  body: JSON.stringify(payload),
66
55
  keepalive: true
67
- }).catch(() => { });
56
+ }).catch(() => {
57
+ // Silent fail (Fire & Forget) to ensure no impact on host app
58
+ });
68
59
  }, 0);
69
60
  }
70
61
 
@@ -144,6 +135,12 @@ if (typeof GLOBAL_OBJ.fetch === 'function' && !GLOBAL_OBJ.fetch.__dropout_patche
144
135
 
145
136
  GLOBAL_OBJ.fetch = async function (input, init) {
146
137
  const url = typeof input === 'string' ? input : (input && input.url);
138
+
139
+ // GUARD: Avoid infinite loops
140
+ if (url && url.includes(config.captureEndpoint)) {
141
+ return GLOBAL_OBJ.__dropout_original_fetch__(input, init);
142
+ }
143
+
147
144
  const isAI = url && (
148
145
  url.includes('openai.com') ||
149
146
  url.includes('anthropic.com') ||
@@ -317,4 +314,4 @@ module.exports = {
317
314
  lastPromptHash = null;
318
315
  lastResponseHash = null;
319
316
  }
320
- };
317
+ };