elasticdash-test 0.1.17 → 0.1.18-alpha
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/dist/capture/event.d.ts +5 -1
- package/dist/capture/event.d.ts.map +1 -1
- package/dist/cli.js +100 -0
- package/dist/cli.js.map +1 -1
- package/dist/evaluators/llm-judge.js +17 -14
- package/dist/evaluators/types.d.ts +1 -0
- package/dist/execution/tool-runner.d.ts +26 -0
- package/dist/execution/tool-runner.d.ts.map +1 -0
- package/dist/execution/tool-runner.js +270 -0
- package/dist/execution/tool-runner.js.map +1 -0
- package/dist/http.d.ts +2 -0
- package/dist/http.d.ts.map +1 -1
- package/dist/http.js +2 -0
- package/dist/http.js.map +1 -1
- package/dist/index.cjs +4310 -2672
- package/dist/index.d.ts +10 -0
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +7 -0
- package/dist/index.js.map +1 -1
- package/dist/interceptors/ai-interceptor.d.ts.map +1 -1
- package/dist/interceptors/ai-interceptor.js +97 -4
- package/dist/interceptors/ai-interceptor.js.map +1 -1
- package/dist/interceptors/db-auto.d.ts.map +1 -1
- package/dist/interceptors/db-auto.js +116 -24
- package/dist/interceptors/db-auto.js.map +1 -1
- package/dist/interceptors/db.d.ts +5 -0
- package/dist/interceptors/db.d.ts.map +1 -1
- package/dist/interceptors/db.js +93 -15
- package/dist/interceptors/db.js.map +1 -1
- package/dist/interceptors/http.d.ts.map +1 -1
- package/dist/interceptors/http.js +125 -93
- package/dist/interceptors/http.js.map +1 -1
- package/dist/interceptors/telemetry-push.d.ts +15 -0
- package/dist/interceptors/telemetry-push.d.ts.map +1 -1
- package/dist/interceptors/telemetry-push.js +96 -13
- package/dist/interceptors/telemetry-push.js.map +1 -1
- package/dist/interceptors/tool.d.ts.map +1 -1
- package/dist/interceptors/tool.js +42 -5
- package/dist/interceptors/tool.js.map +1 -1
- package/dist/interceptors/workflow-ai.d.ts.map +1 -1
- package/dist/interceptors/workflow-ai.js +46 -2
- package/dist/interceptors/workflow-ai.js.map +1 -1
- package/dist/observability.d.ts +69 -0
- package/dist/observability.d.ts.map +1 -0
- package/dist/observability.js +242 -0
- package/dist/observability.js.map +1 -0
- package/dist/portal-executor.d.ts +30 -0
- package/dist/portal-executor.d.ts.map +1 -0
- package/dist/portal-executor.js +304 -0
- package/dist/portal-executor.js.map +1 -0
- package/dist/portal-server.d.ts +3 -0
- package/dist/portal-server.d.ts.map +1 -0
- package/dist/portal-server.js +265 -0
- package/dist/portal-server.js.map +1 -0
- package/dist/telemetry-batcher.d.ts +43 -0
- package/dist/telemetry-batcher.d.ts.map +1 -0
- package/dist/telemetry-batcher.js +111 -0
- package/dist/telemetry-batcher.js.map +1 -0
- package/dist/trigger-executor.d.ts +12 -0
- package/dist/trigger-executor.d.ts.map +1 -0
- package/dist/trigger-executor.js +83 -0
- package/dist/trigger-executor.js.map +1 -0
- package/dist/types/portal.d.ts +64 -0
- package/dist/types/portal.d.ts.map +1 -0
- package/dist/types/portal.js +2 -0
- package/dist/types/portal.js.map +1 -0
- package/dist/utils/debug.d.ts +3 -0
- package/dist/utils/debug.d.ts.map +1 -0
- package/dist/utils/debug.js +8 -0
- package/dist/utils/debug.js.map +1 -0
- package/dist/utils/redact.d.ts +7 -0
- package/dist/utils/redact.d.ts.map +1 -0
- package/dist/utils/redact.js +26 -0
- package/dist/utils/redact.js.map +1 -0
- package/package.json +9 -1
- package/src/capture/event.ts +5 -1
- package/src/cli.ts +109 -0
- package/src/execution/tool-runner.ts +304 -0
- package/src/http.ts +2 -0
- package/src/index.ts +14 -0
- package/src/interceptors/ai-interceptor.ts +110 -4
- package/src/interceptors/db-auto.ts +121 -25
- package/src/interceptors/db.ts +92 -17
- package/src/interceptors/http.ts +145 -107
- package/src/interceptors/telemetry-push.ts +113 -13
- package/src/interceptors/tool.ts +42 -5
- package/src/interceptors/workflow-ai.ts +49 -2
- package/src/observability.ts +281 -0
- package/src/portal-executor.ts +335 -0
- package/src/portal-server.ts +290 -0
- package/src/telemetry-batcher.ts +143 -0
- package/src/trigger-executor.ts +121 -0
- package/src/types/portal.ts +67 -0
- package/src/utils/debug.ts +8 -0
- package/src/utils/redact.ts +25 -0
|
@@ -0,0 +1,265 @@
|
|
|
1
|
+
import express from 'express';
|
|
2
|
+
import http from 'node:http';
|
|
3
|
+
import { executePortalTask } from './portal-executor.js';
|
|
4
|
+
import { scanTools } from './execution/tool-runner.js';
|
|
5
|
+
import { debugLog } from './utils/debug.js';
|
|
6
|
+
// ---------------------------------------------------------------------------
|
|
7
|
+
// Origin allowlist
|
|
8
|
+
// ---------------------------------------------------------------------------
|
|
9
|
+
function extractHost(url) {
|
|
10
|
+
try {
|
|
11
|
+
return new URL(url).host;
|
|
12
|
+
}
|
|
13
|
+
catch {
|
|
14
|
+
return null;
|
|
15
|
+
}
|
|
16
|
+
}
|
|
17
|
+
function buildAllowedHosts(backendUrl, extra) {
|
|
18
|
+
const hosts = new Set();
|
|
19
|
+
// Always allow localhost variants
|
|
20
|
+
hosts.add('localhost');
|
|
21
|
+
hosts.add('127.0.0.1');
|
|
22
|
+
hosts.add('::1');
|
|
23
|
+
// Allow the configured backend
|
|
24
|
+
const backendHost = extractHost(backendUrl);
|
|
25
|
+
if (backendHost)
|
|
26
|
+
hosts.add(backendHost);
|
|
27
|
+
// Allow explicit extra origins
|
|
28
|
+
if (extra) {
|
|
29
|
+
for (const origin of extra) {
|
|
30
|
+
const h = extractHost(origin);
|
|
31
|
+
if (h)
|
|
32
|
+
hosts.add(h);
|
|
33
|
+
else
|
|
34
|
+
hosts.add(origin); // treat raw hostname as-is
|
|
35
|
+
}
|
|
36
|
+
}
|
|
37
|
+
return hosts;
|
|
38
|
+
}
|
|
39
|
+
function isAllowedOrigin(req, allowedHosts) {
|
|
40
|
+
// Determine the caller's host from multiple headers
|
|
41
|
+
// 1. Origin header (set by browsers and some HTTP clients)
|
|
42
|
+
const origin = req.headers.origin;
|
|
43
|
+
if (origin) {
|
|
44
|
+
const h = extractHost(origin);
|
|
45
|
+
return h !== null && isHostAllowed(h, allowedHosts);
|
|
46
|
+
}
|
|
47
|
+
// 2. Referer header fallback
|
|
48
|
+
const referer = req.headers.referer;
|
|
49
|
+
if (referer) {
|
|
50
|
+
const h = extractHost(referer);
|
|
51
|
+
return h !== null && isHostAllowed(h, allowedHosts);
|
|
52
|
+
}
|
|
53
|
+
// 3. X-Forwarded-For / remote IP — check if it's a local request
|
|
54
|
+
const remoteIp = req.ip ?? req.socket?.remoteAddress ?? '';
|
|
55
|
+
if (remoteIp === '127.0.0.1' || remoteIp === '::1' || remoteIp === '::ffff:127.0.0.1') {
|
|
56
|
+
return true;
|
|
57
|
+
}
|
|
58
|
+
// 4. No origin info — this is a direct server-to-server call.
|
|
59
|
+
// If API key auth is configured and passes, allow it.
|
|
60
|
+
// If no API key is configured, reject unknown-origin requests.
|
|
61
|
+
return false;
|
|
62
|
+
}
|
|
63
|
+
function isHostAllowed(host, allowedHosts) {
|
|
64
|
+
// Exact match (includes port, e.g. "localhost:4573")
|
|
65
|
+
if (allowedHosts.has(host))
|
|
66
|
+
return true;
|
|
67
|
+
// Match without port
|
|
68
|
+
const hostWithoutPort = host.split(':')[0];
|
|
69
|
+
if (allowedHosts.has(hostWithoutPort))
|
|
70
|
+
return true;
|
|
71
|
+
// Match subdomains (e.g. "api.elasticdash.com" matches "elasticdash.com")
|
|
72
|
+
for (const allowed of allowedHosts) {
|
|
73
|
+
if (hostWithoutPort.endsWith('.' + allowed))
|
|
74
|
+
return true;
|
|
75
|
+
}
|
|
76
|
+
return false;
|
|
77
|
+
}
|
|
78
|
+
// ---------------------------------------------------------------------------
|
|
79
|
+
// Server
|
|
80
|
+
// ---------------------------------------------------------------------------
|
|
81
|
+
export async function startPortalServer(options) {
|
|
82
|
+
const port = options.port ?? 4574;
|
|
83
|
+
const backendUrl = options.backendUrl.replace(/\/$/, '');
|
|
84
|
+
const apiKey = options.apiKey;
|
|
85
|
+
const cwd = options.cwd ?? process.cwd();
|
|
86
|
+
// Build allowed-origin set from backendUrl + explicit allowlist + localhost
|
|
87
|
+
const allowedHosts = buildAllowedHosts(backendUrl, options.allowedOrigins);
|
|
88
|
+
console.log(`[elasticdash portal] Allowed origins: ${[...allowedHosts].join(', ')}`);
|
|
89
|
+
// Scan tools at startup
|
|
90
|
+
const tools = scanTools(cwd);
|
|
91
|
+
console.log(`[elasticdash portal] Scanned ${tools.length} tools: ${tools.map(t => t.name).join(', ') || '(none)'}`);
|
|
92
|
+
// Queue state
|
|
93
|
+
const queue = [];
|
|
94
|
+
let processing = null;
|
|
95
|
+
let completed = 0;
|
|
96
|
+
let failed = 0;
|
|
97
|
+
let draining = false;
|
|
98
|
+
// -------------------------------------------------------------------------
|
|
99
|
+
// Queue processor
|
|
100
|
+
// -------------------------------------------------------------------------
|
|
101
|
+
async function processQueue() {
|
|
102
|
+
if (draining || processing)
|
|
103
|
+
return;
|
|
104
|
+
if (queue.length === 0)
|
|
105
|
+
return;
|
|
106
|
+
const task = queue.shift();
|
|
107
|
+
processing = task.taskId;
|
|
108
|
+
console.log(`[elasticdash portal] Processing task ${task.taskId} (type=${task.type}, name=${task.name}) — ${queue.length} remaining`);
|
|
109
|
+
const result = await executePortalTask(task, cwd, tools);
|
|
110
|
+
if (result.ok) {
|
|
111
|
+
completed++;
|
|
112
|
+
console.log(`[elasticdash portal] Task ${task.taskId} completed (${result.durationMs}ms)`);
|
|
113
|
+
}
|
|
114
|
+
else {
|
|
115
|
+
failed++;
|
|
116
|
+
console.log(`[elasticdash portal] Task ${task.taskId} failed: ${result.error}`);
|
|
117
|
+
}
|
|
118
|
+
processing = null;
|
|
119
|
+
// Deliver result to backend
|
|
120
|
+
await deliverResult(result);
|
|
121
|
+
// Process next task
|
|
122
|
+
processQueue().catch(() => { });
|
|
123
|
+
}
|
|
124
|
+
async function deliverResult(result) {
|
|
125
|
+
const url = `${backendUrl}/api/portal/results/${result.taskId}`;
|
|
126
|
+
const headers = { 'Content-Type': 'application/json' };
|
|
127
|
+
if (apiKey)
|
|
128
|
+
headers['Authorization'] = `Bearer ${apiKey}`;
|
|
129
|
+
for (let attempt = 0; attempt < 3; attempt++) {
|
|
130
|
+
try {
|
|
131
|
+
const res = await fetch(url, {
|
|
132
|
+
method: 'POST',
|
|
133
|
+
headers,
|
|
134
|
+
body: JSON.stringify(result),
|
|
135
|
+
});
|
|
136
|
+
if (res.ok || res.status < 500) {
|
|
137
|
+
debugLog(`[elasticdash portal] Result delivered for task ${result.taskId} (status ${res.status})`);
|
|
138
|
+
return;
|
|
139
|
+
}
|
|
140
|
+
debugLog(`[elasticdash portal] Result delivery failed (status ${res.status}), attempt ${attempt + 1}/3`);
|
|
141
|
+
}
|
|
142
|
+
catch (e) {
|
|
143
|
+
debugLog(`[elasticdash portal] Result delivery error, attempt ${attempt + 1}/3: ${e instanceof Error ? e.message : String(e)}`);
|
|
144
|
+
}
|
|
145
|
+
if (attempt < 2) {
|
|
146
|
+
await new Promise(r => setTimeout(r, Math.pow(2, attempt) * 1000));
|
|
147
|
+
}
|
|
148
|
+
}
|
|
149
|
+
console.warn(`[elasticdash portal] WARNING: Failed to deliver result for task ${result.taskId} after 3 retries`);
|
|
150
|
+
}
|
|
151
|
+
// -------------------------------------------------------------------------
|
|
152
|
+
// Security middleware: origin allowlist + API key auth
|
|
153
|
+
// -------------------------------------------------------------------------
|
|
154
|
+
function securityMiddleware(req, res, next) {
|
|
155
|
+
// Check API key first — a valid key overrides origin checks
|
|
156
|
+
if (apiKey) {
|
|
157
|
+
const authHeader = req.headers.authorization;
|
|
158
|
+
if (authHeader === `Bearer ${apiKey}`)
|
|
159
|
+
return next();
|
|
160
|
+
}
|
|
161
|
+
// Check origin allowlist
|
|
162
|
+
if (isAllowedOrigin(req, allowedHosts)) {
|
|
163
|
+
// If API key is configured but not provided, still reject
|
|
164
|
+
if (apiKey) {
|
|
165
|
+
res.status(401).json({ ok: false, error: 'unauthorized — valid API key required' });
|
|
166
|
+
return;
|
|
167
|
+
}
|
|
168
|
+
return next();
|
|
169
|
+
}
|
|
170
|
+
// Origin not in allowlist and no valid API key
|
|
171
|
+
const origin = req.headers.origin ?? req.headers.referer ?? req.ip ?? 'unknown';
|
|
172
|
+
console.warn(`[elasticdash portal] Blocked request from disallowed origin: ${origin}`);
|
|
173
|
+
res.status(403).json({ ok: false, error: 'forbidden — origin not in allowlist' });
|
|
174
|
+
}
|
|
175
|
+
// -------------------------------------------------------------------------
|
|
176
|
+
// Express app
|
|
177
|
+
// -------------------------------------------------------------------------
|
|
178
|
+
const app = express();
|
|
179
|
+
app.use(express.json({ limit: '10mb' }));
|
|
180
|
+
// POST /api/portal/tasks — enqueue a single task
|
|
181
|
+
app.post('/api/portal/tasks', securityMiddleware, (req, res) => {
|
|
182
|
+
const task = req.body;
|
|
183
|
+
if (!task?.taskId || !task?.type || !task?.name) {
|
|
184
|
+
res.status(400).json({ ok: false, error: 'Missing required fields: taskId, type, name' });
|
|
185
|
+
return;
|
|
186
|
+
}
|
|
187
|
+
queue.push(task);
|
|
188
|
+
const position = queue.length;
|
|
189
|
+
debugLog(`[elasticdash portal] Task ${task.taskId} enqueued at position ${position}`);
|
|
190
|
+
res.status(202).json({ ok: true, taskId: task.taskId, position });
|
|
191
|
+
processQueue().catch(() => { });
|
|
192
|
+
});
|
|
193
|
+
// POST /api/portal/tasks/batch — enqueue multiple tasks
|
|
194
|
+
app.post('/api/portal/tasks/batch', securityMiddleware, (req, res) => {
|
|
195
|
+
const body = req.body;
|
|
196
|
+
if (!Array.isArray(body?.tasks) || body.tasks.length === 0) {
|
|
197
|
+
res.status(400).json({ ok: false, error: 'Missing or empty tasks array' });
|
|
198
|
+
return;
|
|
199
|
+
}
|
|
200
|
+
const results = [];
|
|
201
|
+
for (const task of body.tasks) {
|
|
202
|
+
if (!task?.taskId || !task?.type || !task?.name)
|
|
203
|
+
continue;
|
|
204
|
+
queue.push(task);
|
|
205
|
+
results.push({ taskId: task.taskId, position: queue.length });
|
|
206
|
+
}
|
|
207
|
+
debugLog(`[elasticdash portal] Batch enqueued ${results.length} tasks`);
|
|
208
|
+
res.status(202).json({ ok: true, tasks: results });
|
|
209
|
+
processQueue().catch(() => { });
|
|
210
|
+
});
|
|
211
|
+
// GET /api/portal/status — health check
|
|
212
|
+
app.get('/api/portal/status', (_req, res) => {
|
|
213
|
+
const status = {
|
|
214
|
+
ok: true,
|
|
215
|
+
queueLength: queue.length,
|
|
216
|
+
processing,
|
|
217
|
+
completed,
|
|
218
|
+
failed,
|
|
219
|
+
};
|
|
220
|
+
res.json(status);
|
|
221
|
+
});
|
|
222
|
+
// DELETE /api/portal/tasks/:taskId — cancel a pending task
|
|
223
|
+
app.delete('/api/portal/tasks/:taskId', securityMiddleware, (req, res) => {
|
|
224
|
+
const taskId = req.params.taskId;
|
|
225
|
+
const index = queue.findIndex(t => t.taskId === taskId);
|
|
226
|
+
if (index === -1) {
|
|
227
|
+
res.status(404).json({ ok: false, error: 'Task not found in queue (may be already processing or completed)' });
|
|
228
|
+
return;
|
|
229
|
+
}
|
|
230
|
+
queue.splice(index, 1);
|
|
231
|
+
res.json({ ok: true, taskId });
|
|
232
|
+
});
|
|
233
|
+
// -------------------------------------------------------------------------
|
|
234
|
+
// Start server
|
|
235
|
+
// -------------------------------------------------------------------------
|
|
236
|
+
const server = http.createServer(app);
|
|
237
|
+
await new Promise((resolve, reject) => {
|
|
238
|
+
server.on('error', reject);
|
|
239
|
+
server.listen(port, () => resolve());
|
|
240
|
+
});
|
|
241
|
+
const url = `http://localhost:${port}`;
|
|
242
|
+
return {
|
|
243
|
+
port,
|
|
244
|
+
url,
|
|
245
|
+
close: async () => {
|
|
246
|
+
draining = true;
|
|
247
|
+
// Wait for current task to finish if processing
|
|
248
|
+
if (processing) {
|
|
249
|
+
console.log(`[elasticdash portal] Waiting for current task ${processing} to finish...`);
|
|
250
|
+
await new Promise((resolve) => {
|
|
251
|
+
const check = setInterval(() => {
|
|
252
|
+
if (!processing) {
|
|
253
|
+
clearInterval(check);
|
|
254
|
+
resolve();
|
|
255
|
+
}
|
|
256
|
+
}, 200);
|
|
257
|
+
});
|
|
258
|
+
}
|
|
259
|
+
await new Promise((resolve, reject) => {
|
|
260
|
+
server.close((err) => err ? reject(err) : resolve());
|
|
261
|
+
});
|
|
262
|
+
},
|
|
263
|
+
};
|
|
264
|
+
}
|
|
265
|
+
//# sourceMappingURL=portal-server.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"portal-server.js","sourceRoot":"","sources":["../src/portal-server.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
import type { WorkflowEvent } from './capture/event.js';
|
|
2
|
+
export interface TriggerStep {
|
|
3
|
+
eventId: number;
|
|
4
|
+
eventType: 'ai' | 'tool';
|
|
5
|
+
eventName: string;
|
|
6
|
+
originalEventDbId: number;
|
|
7
|
+
input: unknown;
|
|
8
|
+
model?: string;
|
|
9
|
+
provider?: string;
|
|
10
|
+
}
|
|
11
|
+
export interface TriggerSignal {
|
|
12
|
+
triggerId: number;
|
|
13
|
+
runCount: number;
|
|
14
|
+
steps: TriggerStep[];
|
|
15
|
+
}
|
|
16
|
+
export interface TelemetryBatcherOptions {
|
|
17
|
+
serverUrl: string;
|
|
18
|
+
apiKey?: string;
|
|
19
|
+
sessionId: string;
|
|
20
|
+
serviceId: string;
|
|
21
|
+
batchIntervalMs?: number;
|
|
22
|
+
maxBatchSize?: number;
|
|
23
|
+
redactKeys?: string[];
|
|
24
|
+
onTrigger?: (trigger: TriggerSignal) => Promise<void>;
|
|
25
|
+
}
|
|
26
|
+
export declare class TelemetryBatcher {
|
|
27
|
+
private buffer;
|
|
28
|
+
private timer;
|
|
29
|
+
private readonly serverUrl;
|
|
30
|
+
private readonly apiKey;
|
|
31
|
+
private readonly sessionId;
|
|
32
|
+
private readonly serviceId;
|
|
33
|
+
private readonly maxBatchSize;
|
|
34
|
+
private readonly redactKeys;
|
|
35
|
+
private readonly onTrigger;
|
|
36
|
+
private shuttingDown;
|
|
37
|
+
constructor(opts: TelemetryBatcherOptions);
|
|
38
|
+
enqueue(event: WorkflowEvent): void;
|
|
39
|
+
flush(): Promise<void>;
|
|
40
|
+
private send;
|
|
41
|
+
shutdown(): Promise<void>;
|
|
42
|
+
}
|
|
43
|
+
//# sourceMappingURL=telemetry-batcher.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"telemetry-batcher.d.ts","sourceRoot":"","sources":["../src/telemetry-batcher.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,oBAAoB,CAAA;AAIvD,MAAM,WAAW,WAAW;IAC1B,OAAO,EAAE,MAAM,CAAA;IACf,SAAS,EAAE,IAAI,GAAG,MAAM,CAAA;IACxB,SAAS,EAAE,MAAM,CAAA;IACjB,iBAAiB,EAAE,MAAM,CAAA;IACzB,KAAK,EAAE,OAAO,CAAA;IACd,KAAK,CAAC,EAAE,MAAM,CAAA;IACd,QAAQ,CAAC,EAAE,MAAM,CAAA;CAClB;AAED,MAAM,WAAW,aAAa;IAC5B,SAAS,EAAE,MAAM,CAAA;IACjB,QAAQ,EAAE,MAAM,CAAA;IAChB,KAAK,EAAE,WAAW,EAAE,CAAA;CACrB;AAED,MAAM,WAAW,uBAAuB;IACtC,SAAS,EAAE,MAAM,CAAA;IACjB,MAAM,CAAC,EAAE,MAAM,CAAA;IACf,SAAS,EAAE,MAAM,CAAA;IACjB,SAAS,EAAE,MAAM,CAAA;IACjB,eAAe,CAAC,EAAE,MAAM,CAAA;IACxB,YAAY,CAAC,EAAE,MAAM,CAAA;IACrB,UAAU,CAAC,EAAE,MAAM,EAAE,CAAA;IACrB,SAAS,CAAC,EAAE,CAAC,OAAO,EAAE,aAAa,KAAK,OAAO,CAAC,IAAI,CAAC,CAAA;CACtD;AAED,qBAAa,gBAAgB;IAC3B,OAAO,CAAC,MAAM,CAAsB;IACpC,OAAO,CAAC,KAAK,CAA8C;IAC3D,OAAO,CAAC,QAAQ,CAAC,SAAS,CAAQ;IAClC,OAAO,CAAC,QAAQ,CAAC,MAAM,CAAoB;IAC3C,OAAO,CAAC,QAAQ,CAAC,SAAS,CAAQ;IAClC,OAAO,CAAC,QAAQ,CAAC,SAAS,CAAQ;IAClC,OAAO,CAAC,QAAQ,CAAC,YAAY,CAAQ;IACrC,OAAO,CAAC,QAAQ,CAAC,UAAU,CAAU;IACrC,OAAO,CAAC,QAAQ,CAAC,SAAS,CAAyD;IACnF,OAAO,CAAC,YAAY,CAAQ;gBAEhB,IAAI,EAAE,uBAAuB;IAiBzC,OAAO,CAAC,KAAK,EAAE,aAAa,GAAG,IAAI;IAW7B,KAAK,IAAI,OAAO,CAAC,IAAI,CAAC;YAMd,IAAI;IAwDZ,QAAQ,IAAI,OAAO,CAAC,IAAI,CAAC;CAShC"}
|
|
@@ -0,0 +1,111 @@
|
|
|
1
|
+
import { debugLog } from './utils/debug.js';
|
|
2
|
+
import { redactPayload } from './utils/redact.js';
|
|
3
|
+
export class TelemetryBatcher {
|
|
4
|
+
buffer = [];
|
|
5
|
+
timer = null;
|
|
6
|
+
serverUrl;
|
|
7
|
+
apiKey;
|
|
8
|
+
sessionId;
|
|
9
|
+
serviceId;
|
|
10
|
+
maxBatchSize;
|
|
11
|
+
redactKeys;
|
|
12
|
+
onTrigger;
|
|
13
|
+
shuttingDown = false;
|
|
14
|
+
constructor(opts) {
|
|
15
|
+
this.serverUrl = opts.serverUrl.replace(/\/$/, '');
|
|
16
|
+
this.apiKey = opts.apiKey;
|
|
17
|
+
this.sessionId = opts.sessionId;
|
|
18
|
+
this.serviceId = opts.serviceId;
|
|
19
|
+
this.maxBatchSize = opts.maxBatchSize ?? 50;
|
|
20
|
+
this.redactKeys = opts.redactKeys ?? [];
|
|
21
|
+
this.onTrigger = opts.onTrigger;
|
|
22
|
+
const intervalMs = opts.batchIntervalMs ?? 2000;
|
|
23
|
+
this.timer = setInterval(() => { this.flush().catch(() => { }); }, intervalMs);
|
|
24
|
+
// Allow the process to exit even if the timer is still scheduled
|
|
25
|
+
if (this.timer && typeof this.timer === 'object' && 'unref' in this.timer) {
|
|
26
|
+
this.timer.unref();
|
|
27
|
+
}
|
|
28
|
+
}
|
|
29
|
+
enqueue(event) {
|
|
30
|
+
if (this.shuttingDown)
|
|
31
|
+
return;
|
|
32
|
+
const redacted = this.redactKeys.length > 0
|
|
33
|
+
? { ...event, input: redactPayload(event.input, this.redactKeys), output: redactPayload(event.output, this.redactKeys) }
|
|
34
|
+
: event;
|
|
35
|
+
this.buffer.push(redacted);
|
|
36
|
+
if (this.buffer.length >= this.maxBatchSize) {
|
|
37
|
+
this.flush().catch(() => { });
|
|
38
|
+
}
|
|
39
|
+
}
|
|
40
|
+
async flush() {
|
|
41
|
+
if (this.buffer.length === 0)
|
|
42
|
+
return;
|
|
43
|
+
const batch = this.buffer.splice(0, this.buffer.length);
|
|
44
|
+
await this.send(batch, 0);
|
|
45
|
+
}
|
|
46
|
+
async send(batch, attempt) {
|
|
47
|
+
const maxRetries = 3;
|
|
48
|
+
const url = `${this.serverUrl}/api/observability/events`;
|
|
49
|
+
const headers = { 'Content-Type': 'application/json' };
|
|
50
|
+
if (this.apiKey)
|
|
51
|
+
headers['Authorization'] = `Bearer ${this.apiKey}`;
|
|
52
|
+
try {
|
|
53
|
+
const res = await fetch(url, {
|
|
54
|
+
method: 'POST',
|
|
55
|
+
headers,
|
|
56
|
+
body: JSON.stringify({
|
|
57
|
+
sessionId: this.sessionId,
|
|
58
|
+
serviceId: this.serviceId,
|
|
59
|
+
events: batch,
|
|
60
|
+
}),
|
|
61
|
+
});
|
|
62
|
+
if (res.status === 429 || res.status >= 500) {
|
|
63
|
+
if (attempt < maxRetries) {
|
|
64
|
+
const delayMs = Math.pow(2, attempt) * 1000;
|
|
65
|
+
debugLog(`[elasticdash] Telemetry flush failed (${res.status}), retrying in ${delayMs}ms (attempt ${attempt + 1}/${maxRetries})`);
|
|
66
|
+
await new Promise((r) => setTimeout(r, delayMs));
|
|
67
|
+
return this.send(batch, attempt + 1);
|
|
68
|
+
}
|
|
69
|
+
debugLog(`[elasticdash] Dropping ${batch.length} events after ${maxRetries} retries (last status: ${res.status})`);
|
|
70
|
+
return;
|
|
71
|
+
}
|
|
72
|
+
debugLog(`[elasticdash] Flushed ${batch.length} events (status ${res.status})`);
|
|
73
|
+
// Parse response for trigger signal
|
|
74
|
+
if (res.ok && this.onTrigger) {
|
|
75
|
+
try {
|
|
76
|
+
const body = await res.json();
|
|
77
|
+
if (body.trigger && typeof body.trigger.triggerId === 'number' && Array.isArray(body.trigger.steps)) {
|
|
78
|
+
debugLog(`[elasticdash] Trigger received: id=${body.trigger.triggerId} steps=${body.trigger.steps.length} runCount=${body.trigger.runCount}`);
|
|
79
|
+
// Fire-and-forget — don't block the flush pipeline
|
|
80
|
+
this.onTrigger(body.trigger).catch((err) => {
|
|
81
|
+
debugLog(`[elasticdash] Trigger execution failed: ${err instanceof Error ? err.message : String(err)}`);
|
|
82
|
+
});
|
|
83
|
+
}
|
|
84
|
+
}
|
|
85
|
+
catch {
|
|
86
|
+
// Response parsing failed — not critical, ignore
|
|
87
|
+
}
|
|
88
|
+
}
|
|
89
|
+
}
|
|
90
|
+
catch (err) {
|
|
91
|
+
if (attempt < maxRetries) {
|
|
92
|
+
const delayMs = Math.pow(2, attempt) * 1000;
|
|
93
|
+
debugLog(`[elasticdash] Telemetry flush error, retrying in ${delayMs}ms (attempt ${attempt + 1}/${maxRetries})`);
|
|
94
|
+
await new Promise((r) => setTimeout(r, delayMs));
|
|
95
|
+
return this.send(batch, attempt + 1);
|
|
96
|
+
}
|
|
97
|
+
debugLog(`[elasticdash] Dropping ${batch.length} events after ${maxRetries} retries: ${err instanceof Error ? err.message : String(err)}`);
|
|
98
|
+
}
|
|
99
|
+
}
|
|
100
|
+
async shutdown() {
|
|
101
|
+
if (this.shuttingDown)
|
|
102
|
+
return;
|
|
103
|
+
this.shuttingDown = true;
|
|
104
|
+
if (this.timer) {
|
|
105
|
+
clearInterval(this.timer);
|
|
106
|
+
this.timer = null;
|
|
107
|
+
}
|
|
108
|
+
await this.flush();
|
|
109
|
+
}
|
|
110
|
+
}
|
|
111
|
+
//# sourceMappingURL=telemetry-batcher.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"telemetry-batcher.js","sourceRoot":"","sources":["../src/telemetry-batcher.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
import type { TriggerSignal } from './telemetry-batcher.js';
|
|
2
|
+
/**
|
|
3
|
+
* Executes a trigger received from the backend's event batch response.
|
|
4
|
+
*
|
|
5
|
+
* For each step:
|
|
6
|
+
* 1. Pre-validates availability (tool exists? API key set?)
|
|
7
|
+
* 2. If unavailable: reports `available: false` with reason, skips execution
|
|
8
|
+
* 3. If available: re-executes `runCount` times, collects results
|
|
9
|
+
* 4. POSTs all results to `POST /api/observability/triggers/:triggerId/results`
|
|
10
|
+
*/
|
|
11
|
+
export declare function executeTrigger(serverUrl: string, apiKey: string | undefined, trigger: TriggerSignal): Promise<void>;
|
|
12
|
+
//# sourceMappingURL=trigger-executor.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"trigger-executor.d.ts","sourceRoot":"","sources":["../src/trigger-executor.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,wBAAwB,CAAA;AAyB3D;;;;;;;;GAQG;AACH,wBAAsB,cAAc,CAClC,SAAS,EAAE,MAAM,EACjB,MAAM,EAAE,MAAM,GAAG,SAAS,EAC1B,OAAO,EAAE,aAAa,GACrB,OAAO,CAAC,IAAI,CAAC,CAkFf"}
|
|
@@ -0,0 +1,83 @@
|
|
|
1
|
+
import { executePortalTask, checkToolAvailability, checkAIAvailability } from './portal-executor.js';
|
|
2
|
+
import { scanTools } from './execution/tool-runner.js';
|
|
3
|
+
import { debugLog } from './utils/debug.js';
|
|
4
|
+
/**
|
|
5
|
+
* Executes a trigger received from the backend's event batch response.
|
|
6
|
+
*
|
|
7
|
+
* For each step:
|
|
8
|
+
* 1. Pre-validates availability (tool exists? API key set?)
|
|
9
|
+
* 2. If unavailable: reports `available: false` with reason, skips execution
|
|
10
|
+
* 3. If available: re-executes `runCount` times, collects results
|
|
11
|
+
* 4. POSTs all results to `POST /api/observability/triggers/:triggerId/results`
|
|
12
|
+
*/
|
|
13
|
+
export async function executeTrigger(serverUrl, apiKey, trigger) {
|
|
14
|
+
const cwd = process.cwd();
|
|
15
|
+
const tools = scanTools(cwd);
|
|
16
|
+
debugLog(`[elasticdash] Executing trigger ${trigger.triggerId}: ${trigger.steps.length} steps × ${trigger.runCount} runs`);
|
|
17
|
+
const stepResults = [];
|
|
18
|
+
for (const step of trigger.steps) {
|
|
19
|
+
// Pre-validate availability
|
|
20
|
+
const availability = step.eventType === 'ai'
|
|
21
|
+
? checkAIAvailability(step.provider, step.model ?? step.eventName)
|
|
22
|
+
: checkToolAvailability(step.eventName, cwd, tools);
|
|
23
|
+
if (!availability.available) {
|
|
24
|
+
debugLog(`[elasticdash] Trigger ${trigger.triggerId} step=${step.eventName} unavailable: ${availability.reason}`);
|
|
25
|
+
stepResults.push({
|
|
26
|
+
originalEventDbId: step.originalEventDbId,
|
|
27
|
+
eventType: step.eventType,
|
|
28
|
+
eventName: step.eventName,
|
|
29
|
+
available: false,
|
|
30
|
+
unavailableReason: availability.reason,
|
|
31
|
+
runs: [],
|
|
32
|
+
});
|
|
33
|
+
continue;
|
|
34
|
+
}
|
|
35
|
+
// Execute runs
|
|
36
|
+
const runs = [];
|
|
37
|
+
for (let i = 0; i < trigger.runCount; i++) {
|
|
38
|
+
const result = await executePortalTask({
|
|
39
|
+
taskId: `trigger-${trigger.triggerId}-${step.eventName}-${i}`,
|
|
40
|
+
type: step.eventType === 'ai' ? 'ai' : 'tool',
|
|
41
|
+
name: step.eventName,
|
|
42
|
+
input: step.input,
|
|
43
|
+
model: step.eventType === 'ai' ? (step.model ?? step.eventName) : undefined,
|
|
44
|
+
provider: step.provider,
|
|
45
|
+
}, cwd, tools);
|
|
46
|
+
runs.push({
|
|
47
|
+
runIndex: i,
|
|
48
|
+
input: step.input,
|
|
49
|
+
output: result.output,
|
|
50
|
+
durationMs: result.durationMs,
|
|
51
|
+
error: result.error,
|
|
52
|
+
usageInputTokens: result.usage?.inputTokens,
|
|
53
|
+
usageOutputTokens: result.usage?.outputTokens,
|
|
54
|
+
usageTotalTokens: result.usage?.totalTokens,
|
|
55
|
+
});
|
|
56
|
+
debugLog(`[elasticdash] Trigger ${trigger.triggerId} step=${step.eventName} run=${i} ok=${result.ok}`);
|
|
57
|
+
}
|
|
58
|
+
stepResults.push({
|
|
59
|
+
originalEventDbId: step.originalEventDbId,
|
|
60
|
+
eventType: step.eventType,
|
|
61
|
+
eventName: step.eventName,
|
|
62
|
+
available: true,
|
|
63
|
+
runs,
|
|
64
|
+
});
|
|
65
|
+
}
|
|
66
|
+
// POST results to backend
|
|
67
|
+
const url = `${serverUrl.replace(/\/$/, '')}/api/observability/triggers/${trigger.triggerId}/results`;
|
|
68
|
+
const headers = { 'Content-Type': 'application/json' };
|
|
69
|
+
if (apiKey)
|
|
70
|
+
headers['Authorization'] = `Bearer ${apiKey}`;
|
|
71
|
+
try {
|
|
72
|
+
const res = await fetch(url, {
|
|
73
|
+
method: 'POST',
|
|
74
|
+
headers,
|
|
75
|
+
body: JSON.stringify({ steps: stepResults }),
|
|
76
|
+
});
|
|
77
|
+
debugLog(`[elasticdash] Trigger ${trigger.triggerId} results posted (status ${res.status})`);
|
|
78
|
+
}
|
|
79
|
+
catch (err) {
|
|
80
|
+
debugLog(`[elasticdash] Trigger ${trigger.triggerId} results POST failed: ${err instanceof Error ? err.message : String(err)}`);
|
|
81
|
+
}
|
|
82
|
+
}
|
|
83
|
+
//# sourceMappingURL=trigger-executor.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"trigger-executor.js","sourceRoot":"","sources":["../src/trigger-executor.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,iBAAiB,EAAE,qBAAqB,EAAE,mBAAmB,EAAE,MAAM,sBAAsB,CAAA;AACpG,OAAO,EAAE,SAAS,EAAE,MAAM,4BAA4B,CAAA;AACtD,OAAO,EAAE,QAAQ,EAAE,MAAM,kBAAkB,CAAA;AAsB3C;;;;;;;;GAQG;AACH,MAAM,CAAC,KAAK,UAAU,cAAc,CAClC,SAAiB,EACjB,MAA0B,EAC1B,OAAsB;IAEtB,MAAM,GAAG,GAAG,OAAO,CAAC,GAAG,EAAE,CAAA;IACzB,MAAM,KAAK,GAAG,SAAS,CAAC,GAAG,CAAC,CAAA;IAE5B,QAAQ,CAAC,mCAAmC,OAAO,CAAC,SAAS,KAAK,OAAO,CAAC,KAAK,CAAC,MAAM,YAAY,OAAO,CAAC,QAAQ,OAAO,CAAC,CAAA;IAE1H,MAAM,WAAW,GAAiB,EAAE,CAAA;IAEpC,KAAK,MAAM,IAAI,IAAI,OAAO,CAAC,KAAK,EAAE,CAAC;QACjC,4BAA4B;QAC5B,MAAM,YAAY,GAAG,IAAI,CAAC,SAAS,KAAK,IAAI;YAC1C,CAAC,CAAC,mBAAmB,CAAC,IAAI,CAAC,QAAQ,EAAE,IAAI,CAAC,KAAK,IAAI,IAAI,CAAC,SAAS,CAAC;YAClE,CAAC,CAAC,qBAAqB,CAAC,IAAI,CAAC,SAAS,EAAE,GAAG,EAAE,KAAK,CAAC,CAAA;QAErD,IAAI,CAAC,YAAY,CAAC,SAAS,EAAE,CAAC;YAC5B,QAAQ,CAAC,yBAAyB,OAAO,CAAC,SAAS,SAAS,IAAI,CAAC,SAAS,iBAAiB,YAAY,CAAC,MAAM,EAAE,CAAC,CAAA;YACjH,WAAW,CAAC,IAAI,CAAC;gBACf,iBAAiB,EAAE,IAAI,CAAC,iBAAiB;gBACzC,SAAS,EAAE,IAAI,CAAC,SAAS;gBACzB,SAAS,EAAE,IAAI,CAAC,SAAS;gBACzB,SAAS,EAAE,KAAK;gBAChB,iBAAiB,EAAE,YAAY,CAAC,MAAM;gBACtC,IAAI,EAAE,EAAE;aACT,CAAC,CAAA;YACF,SAAQ;QACV,CAAC;QAED,eAAe;QACf,MAAM,IAAI,GAAoB,EAAE,CAAA;QAEhC,KAAK,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,OAAO,CAAC,QAAQ,EAAE,CAAC,EAAE,EAAE,CAAC;YAC1C,MAAM,MAAM,GAAG,MAAM,iBAAiB,CACpC;gBACE,MAAM,EAAE,WAAW,OAAO,CAAC,SAAS,IAAI,IAAI,CAAC,SAAS,IAAI,CAAC,EAAE;gBAC7D,IAAI,EAAE,IAAI,CAAC,SAAS,KAAK,IAAI,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,MAAM;gBAC7C,IAAI,EAAE,IAAI,CAAC,SAAS;gBACpB,KAAK,EAAE,IAAI,CAAC,KAAK;gBACjB,KAAK,EAAE,IAAI,CAAC,SAAS,KAAK,IAAI,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,KAAK,IAAI,IAAI,CAAC,SAAS,CAAC,CAAC,CAAC,CAAC,SAAS;gBAC3E,QAAQ,EAAE,IAAI,CAAC,QAAQ;aACxB,EACD,GAAG,EACH,KAAK,CACN,CAAA;YAED,IAAI,CAAC,IAAI,CAAC;gBACR,QAAQ,EAAE,CAAC;gBACX,KAAK,EAAE,IAAI,CAAC,KAAK;gBACjB,MAAM,EAAE,MAAM,CAAC,MAAM;gBACrB,UAAU,EAAE,MAAM,CAAC,UAAU;gBAC7B,KAAK,EAAE,MAAM,CAAC,KAAK;gBACnB,gBAAgB,EAAE,MAAM,CAAC,KAAK,EAAE,WAAW;gBAC3C,iBAAiB,EAAE,MAAM,CAAC,KAAK,EAAE,YAAY;gBAC7C,gBAAgB,EAAE,MAAM,CAAC,KAAK,EAAE,WAAW;aAC5C,CAAC,CAAA;YAEF,QAAQ,CAAC,yBAAyB,OAAO,CAAC,SAAS,SAAS,IAAI,CAAC,SAAS,QAAQ,CAAC,OAAO,MAAM,CAAC,EAAE,EAAE,CAAC,CAAA;QACxG,CAAC;QAED,WAAW,CAAC,IAAI,CAAC;YACf,iBAAiB,EAAE,IAAI,CAAC,iBAAiB;YACzC,SAAS,EAAE,IAAI,CAAC,SAAS;YACzB,SAAS,EAAE,IAAI,CAAC,SAAS;YACzB,SAAS,EAAE,IAAI;YACf,IAAI;SACL,CAAC,CAAA;IACJ,CAAC;IAED,0BAA0B;IAC1B,MAAM,GAAG,GAAG,GAAG,SAAS,CAAC,OAAO,CAAC,KAAK,EAAE,EAAE,CAAC,+BAA+B,OAAO,CAAC,SAAS,UAAU,CAAA;IACrG,MAAM,OAAO,GAA2B,EAAE,cAAc,EAAE,kBAAkB,EAAE,CAAA;IAC9E,IAAI,MAAM;QAAE,OAAO,CAAC,eAAe,CAAC,GAAG,UAAU,MAAM,EAAE,CAAA;IAEzD,IAAI,CAAC;QACH,MAAM,GAAG,GAAG,MAAM,KAAK,CAAC,GAAG,EAAE;YAC3B,MAAM,EAAE,MAAM;YACd,OAAO;YACP,IAAI,EAAE,IAAI,CAAC,SAAS,CAAC,EAAE,KAAK,EAAE,WAAW,EAAE,CAAC;SAC7C,CAAC,CAAA;QACF,QAAQ,CAAC,yBAAyB,OAAO,CAAC,SAAS,2BAA2B,GAAG,CAAC,MAAM,GAAG,CAAC,CAAA;IAC9F,CAAC;IAAC,OAAO,GAAG,EAAE,CAAC;QACb,QAAQ,CAAC,yBAAyB,OAAO,CAAC,SAAS,yBAAyB,GAAG,YAAY,KAAK,CAAC,CAAC,CAAC,GAAG,CAAC,OAAO,CAAC,CAAC,CAAC,MAAM,CAAC,GAAG,CAAC,EAAE,CAAC,CAAA;IACjI,CAAC;AACH,CAAC"}
|
|
@@ -0,0 +1,64 @@
|
|
|
1
|
+
export interface PortalTask {
|
|
2
|
+
/** Unique task ID assigned by the backend */
|
|
3
|
+
taskId: string;
|
|
4
|
+
/** What to rerun */
|
|
5
|
+
type: 'tool' | 'ai';
|
|
6
|
+
/** Tool name or model name */
|
|
7
|
+
name: string;
|
|
8
|
+
/** Tool arguments or LLM prompt/messages */
|
|
9
|
+
input: unknown;
|
|
10
|
+
/** Model name (for AI tasks) */
|
|
11
|
+
model?: string;
|
|
12
|
+
/** LLM provider: openai, anthropic, gemini, grok, etc. */
|
|
13
|
+
provider?: string;
|
|
14
|
+
/** LLM generation parameters */
|
|
15
|
+
modelParameters?: {
|
|
16
|
+
temperature?: number;
|
|
17
|
+
max_tokens?: number;
|
|
18
|
+
};
|
|
19
|
+
/** Passthrough metadata (test group ID, expectation IDs, etc.) */
|
|
20
|
+
metadata?: Record<string, unknown>;
|
|
21
|
+
}
|
|
22
|
+
export interface PortalTaskResult {
|
|
23
|
+
taskId: string;
|
|
24
|
+
ok: boolean;
|
|
25
|
+
output: unknown;
|
|
26
|
+
error?: string;
|
|
27
|
+
durationMs: number;
|
|
28
|
+
usage?: {
|
|
29
|
+
inputTokens?: number;
|
|
30
|
+
outputTokens?: number;
|
|
31
|
+
totalTokens?: number;
|
|
32
|
+
};
|
|
33
|
+
/** Echoed from the original task */
|
|
34
|
+
metadata?: Record<string, unknown>;
|
|
35
|
+
}
|
|
36
|
+
export interface PortalServerOptions {
|
|
37
|
+
/** Port to listen on (default 4574) */
|
|
38
|
+
port?: number;
|
|
39
|
+
/** Backend URL to POST results to */
|
|
40
|
+
backendUrl: string;
|
|
41
|
+
/** Auth token for incoming and outgoing requests */
|
|
42
|
+
apiKey?: string;
|
|
43
|
+
/** Project root directory (default process.cwd()) */
|
|
44
|
+
cwd?: string;
|
|
45
|
+
/**
|
|
46
|
+
* Allowed origin domains that may send requests to this portal.
|
|
47
|
+
* By default only the `backendUrl` domain and localhost are allowed.
|
|
48
|
+
* Provide additional origins (e.g. 'https://app.elasticdash.com') to extend.
|
|
49
|
+
*/
|
|
50
|
+
allowedOrigins?: string[];
|
|
51
|
+
}
|
|
52
|
+
export interface PortalServerHandle {
|
|
53
|
+
port: number;
|
|
54
|
+
url: string;
|
|
55
|
+
close: () => Promise<void>;
|
|
56
|
+
}
|
|
57
|
+
export interface PortalStatus {
|
|
58
|
+
ok: boolean;
|
|
59
|
+
queueLength: number;
|
|
60
|
+
processing: string | null;
|
|
61
|
+
completed: number;
|
|
62
|
+
failed: number;
|
|
63
|
+
}
|
|
64
|
+
//# sourceMappingURL=portal.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"portal.d.ts","sourceRoot":"","sources":["../../src/types/portal.ts"],"names":[],"mappings":"AAAA,MAAM,WAAW,UAAU;IACzB,6CAA6C;IAC7C,MAAM,EAAE,MAAM,CAAA;IACd,oBAAoB;IACpB,IAAI,EAAE,MAAM,GAAG,IAAI,CAAA;IACnB,8BAA8B;IAC9B,IAAI,EAAE,MAAM,CAAA;IACZ,4CAA4C;IAC5C,KAAK,EAAE,OAAO,CAAA;IACd,gCAAgC;IAChC,KAAK,CAAC,EAAE,MAAM,CAAA;IACd,0DAA0D;IAC1D,QAAQ,CAAC,EAAE,MAAM,CAAA;IACjB,gCAAgC;IAChC,eAAe,CAAC,EAAE;QAChB,WAAW,CAAC,EAAE,MAAM,CAAA;QACpB,UAAU,CAAC,EAAE,MAAM,CAAA;KACpB,CAAA;IACD,kEAAkE;IAClE,QAAQ,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAA;CACnC;AAED,MAAM,WAAW,gBAAgB;IAC/B,MAAM,EAAE,MAAM,CAAA;IACd,EAAE,EAAE,OAAO,CAAA;IACX,MAAM,EAAE,OAAO,CAAA;IACf,KAAK,CAAC,EAAE,MAAM,CAAA;IACd,UAAU,EAAE,MAAM,CAAA;IAClB,KAAK,CAAC,EAAE;QACN,WAAW,CAAC,EAAE,MAAM,CAAA;QACpB,YAAY,CAAC,EAAE,MAAM,CAAA;QACrB,WAAW,CAAC,EAAE,MAAM,CAAA;KACrB,CAAA;IACD,oCAAoC;IACpC,QAAQ,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAA;CACnC;AAED,MAAM,WAAW,mBAAmB;IAClC,uCAAuC;IACvC,IAAI,CAAC,EAAE,MAAM,CAAA;IACb,qCAAqC;IACrC,UAAU,EAAE,MAAM,CAAA;IAClB,oDAAoD;IACpD,MAAM,CAAC,EAAE,MAAM,CAAA;IACf,qDAAqD;IACrD,GAAG,CAAC,EAAE,MAAM,CAAA;IACZ;;;;OAIG;IACH,cAAc,CAAC,EAAE,MAAM,EAAE,CAAA;CAC1B;AAED,MAAM,WAAW,kBAAkB;IACjC,IAAI,EAAE,MAAM,CAAA;IACZ,GAAG,EAAE,MAAM,CAAA;IACX,KAAK,EAAE,MAAM,OAAO,CAAC,IAAI,CAAC,CAAA;CAC3B;AAED,MAAM,WAAW,YAAY;IAC3B,EAAE,EAAE,OAAO,CAAA;IACX,WAAW,EAAE,MAAM,CAAA;IACnB,UAAU,EAAE,MAAM,GAAG,IAAI,CAAA;IACzB,SAAS,EAAE,MAAM,CAAA;IACjB,MAAM,EAAE,MAAM,CAAA;CACf"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"portal.js","sourceRoot":"","sources":["../../src/types/portal.ts"],"names":[],"mappings":""}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"debug.d.ts","sourceRoot":"","sources":["../../src/utils/debug.ts"],"names":[],"mappings":"AAEA,qGAAqG;AACrG,wBAAgB,QAAQ,CAAC,GAAG,IAAI,EAAE,OAAO,EAAE,GAAG,IAAI,CAIjD"}
|