@dropout-ai/runtime 0.3.9 â 0.3.10
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 +170 -20
- package/bin/init.js +71 -0
- package/package.json +19 -5
- package/src/index.d.ts +33 -0
- package/src/index.js +61 -44
package/README.md
CHANGED
|
@@ -1,36 +1,186 @@
|
|
|
1
|
-
#
|
|
1
|
+
# đĩī¸ Dropout AI Runtime (`@dropout-ai/runtime`)
|
|
2
2
|
|
|
3
|
-
|
|
3
|
+
**Universal AI Behavior Analysis & Capture for Node.js**
|
|
4
4
|
|
|
5
|
-
|
|
5
|
+
Dropout is a lightweight, "install-and-forget" runtime that automatically captures AI interactions (prompts & responses) from your application without requiring code changes. It acts as a passive observer, patching the network layer to ensure you never miss a conversation.
|
|
6
6
|
|
|
7
|
-
|
|
7
|
+
* **đ Universal:** Works with OpenAI, Anthropic, Genkit, LangChain, Axios, and `fetch`.
|
|
8
|
+
* **đĄī¸ Safe:** Designed for production with silent failure modes and browser guards.
|
|
9
|
+
* **⥠Zero-Latency:** Uses fire-and-forget logging to ensure your app stays fast.
|
|
10
|
+
* **đ Auto-Discovery:** Automatically detects framework (Next.js, NestJS) and configures itself.
|
|
8
11
|
|
|
9
|
-
|
|
12
|
+
---
|
|
13
|
+
|
|
14
|
+
## đ Quick Start (Recommended)
|
|
15
|
+
|
|
16
|
+
Run our initialization wizard in your project root. It will detect your framework and automatically create the necessary configuration files.
|
|
17
|
+
|
|
18
|
+
```bash
|
|
19
|
+
npx @dropout-ai/runtime init
|
|
20
|
+
|
|
21
|
+
```
|
|
22
|
+
|
|
23
|
+
*Supports: **Next.js** (App Router), **NestJS**, **Express**, and standard **Node.js** apps.*
|
|
24
|
+
|
|
25
|
+
---
|
|
26
|
+
|
|
27
|
+
## đ ī¸ Manual Installation
|
|
28
|
+
|
|
29
|
+
If you prefer to configure it yourself, install the package and follow the guide for your specific framework.
|
|
10
30
|
|
|
11
31
|
```bash
|
|
12
32
|
npm install @dropout-ai/runtime
|
|
33
|
+
# or
|
|
34
|
+
yarn add @dropout-ai/runtime
|
|
35
|
+
|
|
13
36
|
```
|
|
14
37
|
|
|
15
|
-
|
|
38
|
+
### 1. Next.js (App Router)
|
|
39
|
+
|
|
40
|
+
Next.js uses lazy-loading, so we use `instrumentation.ts` to ensure Dropout loads immediately on server boot.
|
|
41
|
+
|
|
42
|
+
**Create/Edit:** `src/instrumentation.ts` (or `instrumentation.ts` in root)
|
|
43
|
+
|
|
44
|
+
```typescript
|
|
45
|
+
export async function register() {
|
|
46
|
+
// Ensure we only run on the Node.js server runtime
|
|
47
|
+
if (process.env.NEXT_RUNTIME === 'nodejs') {
|
|
48
|
+
await import('@dropout-ai/runtime');
|
|
49
|
+
console.log('â
Dropout AI Monitoring Active');
|
|
50
|
+
}
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
```
|
|
16
54
|
|
|
17
|
-
|
|
55
|
+
### 2. Node.js / Express / Fastify
|
|
56
|
+
|
|
57
|
+
Initialize Dropout at the **very top** of your entry file (`index.js` or `server.js`), before importing other libraries.
|
|
18
58
|
|
|
19
59
|
```javascript
|
|
20
|
-
|
|
60
|
+
// MUST be the first line
|
|
61
|
+
require('@dropout-ai/runtime');
|
|
62
|
+
|
|
63
|
+
const express = require('express');
|
|
64
|
+
const app = express();
|
|
65
|
+
// ... rest of your code
|
|
66
|
+
|
|
21
67
|
```
|
|
22
68
|
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
69
|
+
### 3. NestJS
|
|
70
|
+
|
|
71
|
+
Initialize Dropout inside your `bootstrap()` function before creating the Nest app.
|
|
72
|
+
|
|
73
|
+
**File:** `src/main.ts`
|
|
74
|
+
|
|
75
|
+
```typescript
|
|
76
|
+
import { NestFactory } from '@nestjs/core';
|
|
77
|
+
import { AppModule } from './app.module';
|
|
78
|
+
import Dropout from '@dropout-ai/runtime';
|
|
79
|
+
|
|
80
|
+
async function bootstrap() {
|
|
81
|
+
// â
Initialize first - Sends "Boot Ping" immediately
|
|
82
|
+
new Dropout({
|
|
83
|
+
projectId: process.env.DROPOUT_PROJECT_ID,
|
|
84
|
+
apiKey: process.env.DROPOUT_API_KEY
|
|
85
|
+
});
|
|
86
|
+
|
|
87
|
+
const app = await NestFactory.create(AppModule);
|
|
88
|
+
await app.listen(3000);
|
|
89
|
+
}
|
|
90
|
+
bootstrap();
|
|
91
|
+
|
|
92
|
+
```
|
|
93
|
+
|
|
94
|
+
### 4. Docker / Zero-Code Injection
|
|
95
|
+
|
|
96
|
+
You can inject Dropout into any Node.js application without editing a single file by using the Node `--require` flag. This is perfect for Docker containers or PaaS deployments.
|
|
97
|
+
|
|
98
|
+
```bash
|
|
99
|
+
# 1. Set credentials
|
|
100
|
+
export DROPOUT_PROJECT_ID="your_project_id"
|
|
101
|
+
export DROPOUT_API_KEY="dp_live_..."
|
|
102
|
+
|
|
103
|
+
# 2. Run your app with the runtime injected
|
|
104
|
+
node -r @dropout-ai/runtime dist/index.js
|
|
105
|
+
|
|
106
|
+
```
|
|
107
|
+
|
|
108
|
+
---
|
|
109
|
+
|
|
110
|
+
## âī¸ Configuration
|
|
111
|
+
|
|
112
|
+
You can configure Dropout via **Environment Variables** (Recommended) or by passing options to the constructor.
|
|
113
|
+
|
|
114
|
+
| Environment Variable | Config Option | Description | Required |
|
|
115
|
+
| --- | --- | --- | --- |
|
|
116
|
+
| `DROPOUT_PROJECT_ID` | `projectId` | Your Project ID from dashboard. | â
|
|
|
117
|
+
| `DROPOUT_API_KEY` | `apiKey` | Your Secret Key (`dp_live_...`). | â
|
|
|
118
|
+
| `DROPOUT_DEBUG` | `debug` | Set `true` to see logs in console and enable connectivity checks. | No |
|
|
119
|
+
| `DROPOUT_PRIVACY` | `privacy` | `full` (capture text) or `mask` (metadata only). | No |
|
|
120
|
+
|
|
121
|
+
**Example `.env` file:**
|
|
122
|
+
|
|
123
|
+
```bash
|
|
124
|
+
DROPOUT_PROJECT_ID="HomeOS"
|
|
125
|
+
DROPOUT_API_KEY="dp_live_xyz123..."
|
|
126
|
+
DROPOUT_DEBUG="true"
|
|
127
|
+
|
|
128
|
+
```
|
|
129
|
+
|
|
130
|
+
---
|
|
131
|
+
|
|
132
|
+
## đ Supported Environments
|
|
133
|
+
|
|
134
|
+
| Language/Framework | Status | Integration Method |
|
|
135
|
+
| --- | --- | --- |
|
|
136
|
+
| **Node.js** (v18+) | â
Ready | `require('@dropout-ai/runtime')` |
|
|
137
|
+
| **Next.js** | â
Ready | `instrumentation.ts` |
|
|
138
|
+
| **NestJS** | â
Ready | `main.ts` import |
|
|
139
|
+
| **Python / Java / Go** | đ§ Beta | Use REST API (see below) |
|
|
140
|
+
|
|
141
|
+
### Non-Node.js Usage (REST API)
|
|
142
|
+
|
|
143
|
+
If you are using Python, Java, or Go, you can manually send interaction logs to our ingestion endpoint.
|
|
144
|
+
|
|
145
|
+
**Endpoint:** `POST https://hipughmjlwmwjxzyxfzs.supabase.co/functions/v1/capture-sealed`
|
|
146
|
+
|
|
147
|
+
**Headers:**
|
|
148
|
+
|
|
149
|
+
* `Content-Type: application/json`
|
|
150
|
+
* `x-dropout-key: YOUR_API_KEY`
|
|
151
|
+
|
|
152
|
+
**Payload:**
|
|
153
|
+
|
|
154
|
+
```json
|
|
155
|
+
{
|
|
156
|
+
"project_id": "your_project_id",
|
|
157
|
+
"turn_role": "assistant", // or "user"
|
|
158
|
+
"content": "AI response text...",
|
|
159
|
+
"model": "gpt-4", // optional
|
|
160
|
+
"provider": "openai", // optional
|
|
161
|
+
"latency_ms": 1250 // optional
|
|
162
|
+
}
|
|
163
|
+
|
|
164
|
+
```
|
|
165
|
+
|
|
166
|
+
---
|
|
167
|
+
|
|
168
|
+
## â Troubleshooting
|
|
169
|
+
|
|
170
|
+
**Q: I don't see any logs in the dashboard.**
|
|
171
|
+
|
|
172
|
+
1. Ensure `DROPOUT_DEBUG="true"` is set.
|
|
173
|
+
2. Check your console for `[Dropout] đĸ Online: <ProjectID>`.
|
|
174
|
+
3. If using Next.js, ensure you created `instrumentation.ts` in the correct folder (root or `src`).
|
|
175
|
+
|
|
176
|
+
**Q: Does this work with Edge Functions (Vercel Edge / Cloudflare)?**
|
|
177
|
+
No. This runtime relies on Node.js core modules (`http`, `https`) to capture traffic. It does not currently support Vercel Edge Runtime or Cloudflare Workers. Please ensure your API routes use the Node.js runtime.
|
|
178
|
+
|
|
179
|
+
**Q: Will this crash my app if the API is down?**
|
|
180
|
+
No. The SDK is built with a "Safety Fuse." If it cannot connect or encounters an error, it fails silently and your application continues running without interruption.
|
|
181
|
+
|
|
182
|
+
---
|
|
28
183
|
|
|
29
|
-
|
|
30
|
-
- **Zero Configuration**: Just import and it works.
|
|
31
|
-
- **Invisible capture**: No code changes to your AI logic.
|
|
32
|
-
- **Non-blocking**: Uses fire-and-forget network calls.
|
|
33
|
-
- **Remote Config**: Supports dynamic output capping and provider filtering.
|
|
184
|
+
### License
|
|
34
185
|
|
|
35
|
-
|
|
36
|
-
MIT
|
|
186
|
+
MIT
|
package/bin/init.js
ADDED
|
@@ -0,0 +1,71 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
const fs = require('fs');
|
|
3
|
+
const path = require('path');
|
|
4
|
+
|
|
5
|
+
const colors = {
|
|
6
|
+
reset: "\x1b[0m",
|
|
7
|
+
green: "\x1b[32m",
|
|
8
|
+
yellow: "\x1b[33m",
|
|
9
|
+
cyan: "\x1b[36m"
|
|
10
|
+
};
|
|
11
|
+
|
|
12
|
+
const log = (color, msg) => console.log(`${color}${msg}${colors.reset}`);
|
|
13
|
+
|
|
14
|
+
function detectFramework() {
|
|
15
|
+
const cwd = process.cwd();
|
|
16
|
+
if (fs.existsSync(path.resolve(cwd, 'package.json'))) {
|
|
17
|
+
const pkg = JSON.parse(fs.readFileSync(path.resolve(cwd, 'package.json'), 'utf-8'));
|
|
18
|
+
const deps = { ...pkg.dependencies, ...pkg.devDependencies };
|
|
19
|
+
if (deps.next) return 'nextjs';
|
|
20
|
+
if (deps['@nestjs/core']) return 'nestjs';
|
|
21
|
+
return 'node';
|
|
22
|
+
}
|
|
23
|
+
return 'unknown';
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
function setupNextJs() {
|
|
27
|
+
log(colors.cyan, 'đ Next.js project detected.');
|
|
28
|
+
const hasSrc = fs.existsSync(path.resolve(process.cwd(), 'src'));
|
|
29
|
+
const targetDir = hasSrc ? 'src' : '.';
|
|
30
|
+
const isTs = fs.existsSync(path.resolve(process.cwd(), 'tsconfig.json'));
|
|
31
|
+
const ext = isTs ? 'ts' : 'js';
|
|
32
|
+
const filePath = path.resolve(process.cwd(), targetDir, `instrumentation.${ext}`);
|
|
33
|
+
|
|
34
|
+
const content = `export async function register() {
|
|
35
|
+
if (process.env.NEXT_RUNTIME === 'nodejs') {
|
|
36
|
+
await import('@dropout-ai/runtime');
|
|
37
|
+
console.log('[Dropout] đĸ Initialized via instrumentation hook');
|
|
38
|
+
}
|
|
39
|
+
}`;
|
|
40
|
+
|
|
41
|
+
if (fs.existsSync(filePath)) {
|
|
42
|
+
log(colors.yellow, `â ī¸ File exists: ${filePath}`);
|
|
43
|
+
log(colors.yellow, `đ Please add the register() hook manually.`);
|
|
44
|
+
} else {
|
|
45
|
+
fs.writeFileSync(filePath, content);
|
|
46
|
+
log(colors.green, `â
Created: ${targetDir}/instrumentation.${ext}`);
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
log(colors.cyan, '\nNEXT STEP: Add .env keys (DROPOUT_PROJECT_ID, DROPOUT_API_KEY).');
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
function run() {
|
|
53
|
+
console.log(colors.cyan + "\nDropout AI - Init Wizard đ§ââī¸" + colors.reset);
|
|
54
|
+
const framework = detectFramework();
|
|
55
|
+
|
|
56
|
+
switch (framework) {
|
|
57
|
+
case 'nextjs': setupNextJs(); break;
|
|
58
|
+
case 'nestjs':
|
|
59
|
+
log(colors.cyan, 'đ NestJS detected.');
|
|
60
|
+
log(colors.green, 'đ Initialize in src/main.ts before bootstrap().');
|
|
61
|
+
break;
|
|
62
|
+
case 'node':
|
|
63
|
+
log(colors.cyan, 'đ Node/Express detected.');
|
|
64
|
+
log(colors.green, 'đ Add require("@dropout-ai/runtime") at the top of index.js.');
|
|
65
|
+
break;
|
|
66
|
+
default:
|
|
67
|
+
log(colors.yellow, 'â ī¸ Unknown framework. Check docs for manual setup.');
|
|
68
|
+
}
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
run();
|
package/package.json
CHANGED
|
@@ -1,16 +1,29 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@dropout-ai/runtime",
|
|
3
|
-
"version": "0.3.
|
|
4
|
-
"description": "Invisible Node.js runtime for
|
|
3
|
+
"version": "0.3.10",
|
|
4
|
+
"description": "Invisible Node.js runtime for understanding behavoiral impact of AI interactions.",
|
|
5
5
|
"main": "src/index.js",
|
|
6
|
+
"types": "src/index.d.ts",
|
|
7
|
+
"bin": {
|
|
8
|
+
"init": "./bin/init.js"
|
|
9
|
+
},
|
|
6
10
|
"scripts": {
|
|
7
|
-
"test": "
|
|
11
|
+
"test": "echo \"Error: no test specified\" && exit 1"
|
|
8
12
|
},
|
|
9
13
|
"keywords": [
|
|
10
14
|
"openai",
|
|
11
15
|
"telemetry",
|
|
12
16
|
"runtime",
|
|
13
|
-
"invisible"
|
|
17
|
+
"invisible",
|
|
18
|
+
"observability",
|
|
19
|
+
"ai",
|
|
20
|
+
"behavoiral analysis",
|
|
21
|
+
"ai forensic",
|
|
22
|
+
"llm",
|
|
23
|
+
"monitoring",
|
|
24
|
+
"genkit",
|
|
25
|
+
"nestjs",
|
|
26
|
+
"nextjs"
|
|
14
27
|
],
|
|
15
28
|
"repository": {
|
|
16
29
|
"type": "git",
|
|
@@ -18,7 +31,8 @@
|
|
|
18
31
|
"directory": "packages/runtime"
|
|
19
32
|
},
|
|
20
33
|
"files": [
|
|
21
|
-
"src"
|
|
34
|
+
"src",
|
|
35
|
+
"bin"
|
|
22
36
|
],
|
|
23
37
|
"publishConfig": {
|
|
24
38
|
"access": "public"
|
package/src/index.d.ts
ADDED
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
export interface DropoutConfig {
|
|
2
|
+
/**
|
|
3
|
+
* Your project ID from the Dropout Dashboard.
|
|
4
|
+
*/
|
|
5
|
+
projectId: string;
|
|
6
|
+
|
|
7
|
+
/**
|
|
8
|
+
* Your secret API Key (starts with dp_live_...).
|
|
9
|
+
*/
|
|
10
|
+
apiKey: string;
|
|
11
|
+
|
|
12
|
+
/**
|
|
13
|
+
* Data Privacy Level.
|
|
14
|
+
* 'full' - Captures prompts and responses (Default).
|
|
15
|
+
* 'mask' - Captures metadata only, redacts text.
|
|
16
|
+
*/
|
|
17
|
+
privacy?: 'full' | 'mask';
|
|
18
|
+
|
|
19
|
+
/**
|
|
20
|
+
* Enable verbose logging for connection debugging.
|
|
21
|
+
* Default: false
|
|
22
|
+
*/
|
|
23
|
+
debug?: boolean;
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
export default class Dropout {
|
|
27
|
+
constructor(config: DropoutConfig);
|
|
28
|
+
|
|
29
|
+
/**
|
|
30
|
+
* Manually log a message to the debug stream.
|
|
31
|
+
*/
|
|
32
|
+
log(msg: string, ...args: any[]): void;
|
|
33
|
+
}
|
package/src/index.js
CHANGED
|
@@ -1,14 +1,13 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* @dropout-ai/runtime
|
|
3
3
|
* Universal AI Interaction Capture for Node.js
|
|
4
|
-
*
|
|
4
|
+
* Stability: High (Browser-Safe, Silent Failures)
|
|
5
|
+
* Features: Auto-Discovery, Connectivity Check, Dual-Schema Support
|
|
5
6
|
*/
|
|
6
7
|
|
|
7
|
-
|
|
8
|
-
const http = require('http');
|
|
9
|
-
const crypto = require('crypto');
|
|
8
|
+
let https, http, crypto;
|
|
10
9
|
|
|
11
|
-
// --- CONFIGURATION ---
|
|
10
|
+
// --- DEFAULT CONFIGURATION ---
|
|
12
11
|
const SUPABASE_FUNCTION_URL = "https://hipughmjlwmwjxzyxfzs.supabase.co/functions/v1/capture-sealed";
|
|
13
12
|
|
|
14
13
|
// Known AI Domains
|
|
@@ -19,53 +18,73 @@ const KNOWN_AI_DOMAINS = [
|
|
|
19
18
|
|
|
20
19
|
class Dropout {
|
|
21
20
|
constructor(config = {}) {
|
|
22
|
-
// đĄī¸ BROWSER GUARD
|
|
21
|
+
// đĄī¸ 1. BROWSER GUARD (Client-Side Protection)
|
|
23
22
|
if (typeof window !== 'undefined' && typeof window.document !== 'undefined') {
|
|
24
|
-
if (config.debug) console.warn("[Dropout] â ī¸ Skipped: Browser detected.");
|
|
23
|
+
if (config.debug) console.warn("[Dropout] â ī¸ Skipped: Browser detected. SDK is Server-Only.");
|
|
25
24
|
return;
|
|
26
25
|
}
|
|
27
26
|
|
|
28
|
-
// đĄī¸ CREDENTIAL GUARD
|
|
27
|
+
// đĄī¸ 2. CREDENTIAL GUARD
|
|
29
28
|
if (!config.apiKey || !config.projectId) {
|
|
30
|
-
if (config.debug) console.warn("[Dropout] â ī¸ Skipped: Missing
|
|
29
|
+
if (config.debug) console.warn("[Dropout] â ī¸ Skipped: Missing API Key or Project ID.");
|
|
31
30
|
return;
|
|
32
31
|
}
|
|
33
32
|
|
|
34
|
-
//
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
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();
|
|
33
|
+
// đĄī¸ 3. DEPENDENCY CHECK
|
|
34
|
+
try {
|
|
35
|
+
https = require('https');
|
|
36
|
+
http = require('http');
|
|
37
|
+
crypto = require('crypto');
|
|
38
|
+
} catch (e) {
|
|
39
|
+
if (config.debug) console.warn("[Dropout] â ī¸ Skipped: Node core modules missing.");
|
|
40
|
+
return;
|
|
55
41
|
}
|
|
56
42
|
|
|
57
|
-
|
|
43
|
+
// --- INITIALIZATION ---
|
|
44
|
+
try {
|
|
45
|
+
this.config = config;
|
|
46
|
+
this.projectId = config.projectId;
|
|
47
|
+
this.apiKey = config.apiKey;
|
|
48
|
+
this.debug = config.debug || false;
|
|
49
|
+
this.privacy = config.privacy || 'full';
|
|
50
|
+
this.captureEndpoint = SUPABASE_FUNCTION_URL;
|
|
51
|
+
this.maxOutputBytes = 32768;
|
|
52
|
+
|
|
53
|
+
// State
|
|
54
|
+
this.turnIndex = 0;
|
|
55
|
+
this.lastTurnConfirmed = true;
|
|
56
|
+
this.lastPromptHash = null;
|
|
57
|
+
this.lastResponseHash = null;
|
|
58
|
+
|
|
59
|
+
// Singleton Guard
|
|
60
|
+
if (global.__dropout_initialized__) {
|
|
61
|
+
if (this.debug) console.log("[Dropout] âšī¸ Already initialized.");
|
|
62
|
+
return;
|
|
63
|
+
}
|
|
64
|
+
global.__dropout_initialized__ = true;
|
|
65
|
+
|
|
66
|
+
// Identity
|
|
67
|
+
if (!global.__dropout_session_id__) {
|
|
68
|
+
global.__dropout_session_id__ = this.generateSessionId();
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
if (this.debug) console.log(`[Dropout] đĸ Online: ${this.projectId}`);
|
|
58
72
|
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
73
|
+
// Bindings
|
|
74
|
+
this.log = this.log.bind(this);
|
|
75
|
+
this.emit = this.emit.bind(this);
|
|
62
76
|
|
|
63
|
-
|
|
64
|
-
|
|
77
|
+
// 4. Start Network Interceptor
|
|
78
|
+
this.patchNetwork();
|
|
65
79
|
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
80
|
+
// 5. SEND STARTUP PING (Always run this, silent by default)
|
|
81
|
+
// This turns the dashboard status GREEN immediately on app boot.
|
|
82
|
+
this.sendStartupSignal();
|
|
83
|
+
|
|
84
|
+
} catch (err) {
|
|
85
|
+
// THE ULTIMATE CATCH-ALL: Ensure app NEVER crashes
|
|
86
|
+
if (config.debug) console.error("[Dropout] â Initialization Error:", err);
|
|
87
|
+
}
|
|
69
88
|
}
|
|
70
89
|
|
|
71
90
|
// --- UTILS ---
|
|
@@ -83,15 +102,13 @@ class Dropout {
|
|
|
83
102
|
|
|
84
103
|
// --- HEARTBEAT ---
|
|
85
104
|
sendStartupSignal() {
|
|
86
|
-
// We send a discrete 'system_boot' event.
|
|
87
|
-
// The Database Trigger will see this and update projects.last_active_at
|
|
88
105
|
const payload = JSON.stringify({
|
|
89
106
|
project_id: this.projectId,
|
|
90
107
|
session_id: 'system_boot_' + Date.now(),
|
|
91
108
|
turn_role: 'system',
|
|
92
109
|
turn_index: 0,
|
|
93
110
|
content: 'Dropout SDK Initialized',
|
|
94
|
-
//content_blob: 'Dropout SDK Initialized',
|
|
111
|
+
// content_blob: 'Dropout SDK Initialized',
|
|
95
112
|
metadata_flags: {
|
|
96
113
|
type: 'system_boot',
|
|
97
114
|
environment: process.env.NODE_ENV || 'development',
|
|
@@ -108,7 +125,6 @@ class Dropout {
|
|
|
108
125
|
}
|
|
109
126
|
});
|
|
110
127
|
|
|
111
|
-
// Silent error handling (unless debug is on)
|
|
112
128
|
req.on('error', (e) => this.log("â Startup Signal Failed", e.message));
|
|
113
129
|
req.write(payload);
|
|
114
130
|
req.end();
|
|
@@ -169,7 +185,7 @@ class Dropout {
|
|
|
169
185
|
model: payload.model,
|
|
170
186
|
latency_ms: payload.latency_ms || null,
|
|
171
187
|
content: payload.content,
|
|
172
|
-
//content_blob: payload.content,
|
|
188
|
+
// content_blob: payload.content,
|
|
173
189
|
content_hash: payload.content_hash,
|
|
174
190
|
metadata_flags: payload.metadata_flags,
|
|
175
191
|
received_at: new Date().toISOString()
|
|
@@ -393,6 +409,7 @@ class Dropout {
|
|
|
393
409
|
}
|
|
394
410
|
}
|
|
395
411
|
|
|
412
|
+
// Auto-Start (Server-Side Only)
|
|
396
413
|
if (typeof process !== 'undefined' && process.env.DROPOUT_PROJECT_ID && process.env.DROPOUT_API_KEY) {
|
|
397
414
|
new Dropout({
|
|
398
415
|
projectId: process.env.DROPOUT_PROJECT_ID,
|