@pranshulsoni/flowwatch 1.0.0
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 +442 -0
- package/dist/ai/groqInsightService.d.ts +39 -0
- package/dist/ai/groqInsightService.js +230 -0
- package/dist/createFlowwatch.d.ts +17 -0
- package/dist/createFlowwatch.js +90 -0
- package/dist/dashboard/routes/dashboardResponse.d.ts +204 -0
- package/dist/dashboard/routes/dashboardResponse.js +248 -0
- package/dist/dashboard/routes/router.d.ts +13 -0
- package/dist/dashboard/routes/router.js +708 -0
- package/dist/dashboard/static/dashboard.html +6061 -0
- package/dist/engine/background/queues/workflowQueue.d.ts +6 -0
- package/dist/engine/background/queues/workflowQueue.js +14 -0
- package/dist/engine/background/workers/workflowWorker.d.ts +15 -0
- package/dist/engine/background/workers/workflowWorker.js +98 -0
- package/dist/engine/errors/errorEngine.d.ts +27 -0
- package/dist/engine/errors/errorEngine.js +115 -0
- package/dist/engine/flags/evaluateFlag.d.ts +3 -0
- package/dist/engine/flags/evaluateFlag.js +50 -0
- package/dist/engine/flags/flagEngine.d.ts +9 -0
- package/dist/engine/flags/flagEngine.js +52 -0
- package/dist/engine/flags/hashRollout.d.ts +1 -0
- package/dist/engine/flags/hashRollout.js +9 -0
- package/dist/engine/flags/types.d.ts +7 -0
- package/dist/engine/flags/types.js +1 -0
- package/dist/engine/trace/traceEngine.d.ts +26 -0
- package/dist/engine/trace/traceEngine.js +76 -0
- package/dist/engine/workflows/types.d.ts +28 -0
- package/dist/engine/workflows/types.js +1 -0
- package/dist/engine/workflows/workflowEngine.d.ts +15 -0
- package/dist/engine/workflows/workflowEngine.js +112 -0
- package/dist/index.d.ts +9 -0
- package/dist/index.js +3 -0
- package/dist/persistence/cache/redisClient.d.ts +2 -0
- package/dist/persistence/cache/redisClient.js +4 -0
- package/dist/persistence/db/postgres.d.ts +3 -0
- package/dist/persistence/db/postgres.js +4 -0
- package/dist/persistence/migrations/migrationRunner.d.ts +3 -0
- package/dist/persistence/migrations/migrationRunner.js +46 -0
- package/dist/persistence/migrations/migrations.d.ts +5 -0
- package/dist/persistence/migrations/migrations.js +191 -0
- package/dist/persistence/repositories/errors/errorRepository.d.ts +38 -0
- package/dist/persistence/repositories/errors/errorRepository.js +63 -0
- package/dist/persistence/repositories/flags/flagRepository.d.ts +72 -0
- package/dist/persistence/repositories/flags/flagRepository.js +245 -0
- package/dist/persistence/repositories/traces/traceRepository.d.ts +64 -0
- package/dist/persistence/repositories/traces/traceRepository.js +110 -0
- package/dist/persistence/repositories/workflows/workflowRepository.d.ts +93 -0
- package/dist/persistence/repositories/workflows/workflowRepository.js +260 -0
- package/dist/persistence/transaction.d.ts +2 -0
- package/dist/persistence/transaction.js +16 -0
- package/dist/runtime/config/normalizeConfig.d.ts +2 -0
- package/dist/runtime/config/normalizeConfig.js +46 -0
- package/dist/runtime/config/validationConfig.d.ts +2 -0
- package/dist/runtime/config/validationConfig.js +119 -0
- package/dist/runtime/health/healthService.d.ts +30 -0
- package/dist/runtime/health/healthService.js +54 -0
- package/dist/runtime/tracing/traceContext.d.ts +12 -0
- package/dist/runtime/tracing/traceContext.js +28 -0
- package/dist/runtime/tracing/tracingMiddleware.d.ts +3 -0
- package/dist/runtime/tracing/tracingMiddleware.js +46 -0
- package/dist/search/elasticsearch/client.d.ts +2 -0
- package/dist/search/elasticsearch/client.js +4 -0
- package/dist/search/elasticsearch/indexSetup.d.ts +3 -0
- package/dist/search/elasticsearch/indexSetup.js +43 -0
- package/dist/search/elasticsearch/indexer.d.ts +9 -0
- package/dist/search/elasticsearch/indexer.js +86 -0
- package/dist/search/elasticsearch/mappingChecker.d.ts +2 -0
- package/dist/search/elasticsearch/mappingChecker.js +28 -0
- package/dist/types/index.d.ts +48 -0
- package/dist/types/index.js +1 -0
- package/dist/utils/flowwatchEnvStore.d.ts +27 -0
- package/dist/utils/flowwatchEnvStore.js +145 -0
- package/package.json +63 -0
|
@@ -0,0 +1,230 @@
|
|
|
1
|
+
import { getGroqApiKey, getGroqModel } from "../utils/flowwatchEnvStore.js";
|
|
2
|
+
const GROQ_CHAT_COMPLETIONS_URL = "https://api.groq.com/openai/v1/chat/completions";
|
|
3
|
+
const GROQ_MODELS_URL = "https://api.groq.com/openai/v1/models";
|
|
4
|
+
const DEFAULT_GROQ_MODEL = "llama-3.3-70b-versatile";
|
|
5
|
+
const ALLOWED_CHAT_ROLES = new Set(["user", "assistant"]);
|
|
6
|
+
const MODEL_ID_PATTERN = /^[a-zA-Z0-9._:/-]{1,128}$/;
|
|
7
|
+
const OUT_OF_SCOPE_RESPONSE = [
|
|
8
|
+
"### Server context only",
|
|
9
|
+
"",
|
|
10
|
+
"Ask Flowwatch AI can only help with this service's workflows, executions, traces, errors, feature flags, health checks, and backend runtime behavior.",
|
|
11
|
+
"",
|
|
12
|
+
"Try asking about:",
|
|
13
|
+
"- Recent failed workflow executions",
|
|
14
|
+
"- Slow traces or request latency",
|
|
15
|
+
"- Captured server errors",
|
|
16
|
+
"- Feature flag rollout impact",
|
|
17
|
+
"- Health check failures",
|
|
18
|
+
].join("\n");
|
|
19
|
+
const SERVER_QUESTION_TERMS = [
|
|
20
|
+
"api",
|
|
21
|
+
"backend",
|
|
22
|
+
"bullmq",
|
|
23
|
+
"cache",
|
|
24
|
+
"database",
|
|
25
|
+
"db",
|
|
26
|
+
"deployment",
|
|
27
|
+
"endpoint",
|
|
28
|
+
"error",
|
|
29
|
+
"exception",
|
|
30
|
+
"execution",
|
|
31
|
+
"express",
|
|
32
|
+
"failure",
|
|
33
|
+
"feature flag",
|
|
34
|
+
"flag",
|
|
35
|
+
"health",
|
|
36
|
+
"incident",
|
|
37
|
+
"latency",
|
|
38
|
+
"log",
|
|
39
|
+
"metric",
|
|
40
|
+
"migration",
|
|
41
|
+
"postgres",
|
|
42
|
+
"queue",
|
|
43
|
+
"redis",
|
|
44
|
+
"request",
|
|
45
|
+
"retry",
|
|
46
|
+
"route",
|
|
47
|
+
"server",
|
|
48
|
+
"service",
|
|
49
|
+
"span",
|
|
50
|
+
"status",
|
|
51
|
+
"throughput",
|
|
52
|
+
"trace",
|
|
53
|
+
"workflow",
|
|
54
|
+
];
|
|
55
|
+
function normalizeInsight(value, context) {
|
|
56
|
+
return {
|
|
57
|
+
summary: String(value?.summary || "No summary returned."),
|
|
58
|
+
likelyCause: String(value?.likelyCause || value?.likely_cause || "Unknown"),
|
|
59
|
+
impact: String(value?.impact || "Unknown"),
|
|
60
|
+
evidence: Array.isArray(value?.evidence) ? value.evidence.map(String).slice(0, 8) : [],
|
|
61
|
+
recommendedActions: Array.isArray(value?.recommendedActions)
|
|
62
|
+
? value.recommendedActions.map(String).slice(0, 8)
|
|
63
|
+
: Array.isArray(value?.recommended_actions)
|
|
64
|
+
? value.recommended_actions.map(String).slice(0, 8)
|
|
65
|
+
: [],
|
|
66
|
+
confidence: Math.max(0, Math.min(100, Number(value?.confidence ?? 0))),
|
|
67
|
+
sourceCounts: {
|
|
68
|
+
workflows: context.workflows.length,
|
|
69
|
+
executions: context.executions.length,
|
|
70
|
+
errors: context.errors.length,
|
|
71
|
+
traces: context.traces.length,
|
|
72
|
+
flags: context.flags.length,
|
|
73
|
+
health: context.health.length,
|
|
74
|
+
},
|
|
75
|
+
};
|
|
76
|
+
}
|
|
77
|
+
function parseInsightJson(content) {
|
|
78
|
+
const trimmed = content.trim();
|
|
79
|
+
const fenced = trimmed.match(/^```(?:json)?\s*([\s\S]*?)\s*```$/);
|
|
80
|
+
return JSON.parse(fenced?.[1] || trimmed);
|
|
81
|
+
}
|
|
82
|
+
function selectedModel(model) {
|
|
83
|
+
const value = model || getGroqModel() || DEFAULT_GROQ_MODEL;
|
|
84
|
+
if (!MODEL_ID_PATTERN.test(value)) {
|
|
85
|
+
throw new Error("Invalid Groq model id");
|
|
86
|
+
}
|
|
87
|
+
return value;
|
|
88
|
+
}
|
|
89
|
+
function sanitizeChatHistory(history) {
|
|
90
|
+
return (history || [])
|
|
91
|
+
.filter((message) => ALLOWED_CHAT_ROLES.has(message?.role))
|
|
92
|
+
.map((message) => ({
|
|
93
|
+
role: message.role,
|
|
94
|
+
content: String(message.content || "").slice(0, 4096),
|
|
95
|
+
}))
|
|
96
|
+
.slice(-50);
|
|
97
|
+
}
|
|
98
|
+
export function isServerObservabilityQuestion(message) {
|
|
99
|
+
const normalized = String(message || "").toLowerCase().replace(/\s+/g, " ").trim();
|
|
100
|
+
if (!normalized)
|
|
101
|
+
return false;
|
|
102
|
+
return SERVER_QUESTION_TERMS.some((term) => normalized.includes(term));
|
|
103
|
+
}
|
|
104
|
+
export function outOfScopeFlowwatchResponse() {
|
|
105
|
+
return OUT_OF_SCOPE_RESPONSE;
|
|
106
|
+
}
|
|
107
|
+
export async function listGroqModels() {
|
|
108
|
+
const apiKey = getGroqApiKey();
|
|
109
|
+
if (!apiKey) {
|
|
110
|
+
throw new Error("GROQ_API_KEY is not configured");
|
|
111
|
+
}
|
|
112
|
+
const response = await fetch(GROQ_MODELS_URL, {
|
|
113
|
+
headers: {
|
|
114
|
+
"Authorization": `Bearer ${apiKey}`,
|
|
115
|
+
"Content-Type": "application/json",
|
|
116
|
+
},
|
|
117
|
+
});
|
|
118
|
+
if (!response.ok) {
|
|
119
|
+
const message = await response.text();
|
|
120
|
+
throw new Error(`Groq model request failed: ${response.status} ${message}`);
|
|
121
|
+
}
|
|
122
|
+
const models = await response.json();
|
|
123
|
+
return Array.isArray(models?.data)
|
|
124
|
+
? models.data
|
|
125
|
+
.map((model) => ({
|
|
126
|
+
id: String(model?.id || ""),
|
|
127
|
+
ownedBy: model?.owned_by ? String(model.owned_by) : undefined,
|
|
128
|
+
}))
|
|
129
|
+
.filter((model) => model.id)
|
|
130
|
+
: [];
|
|
131
|
+
}
|
|
132
|
+
export async function generateGroqInsight(context, model) {
|
|
133
|
+
const apiKey = getGroqApiKey();
|
|
134
|
+
if (!apiKey) {
|
|
135
|
+
throw new Error("GROQ_API_KEY is not configured");
|
|
136
|
+
}
|
|
137
|
+
const response = await fetch(GROQ_CHAT_COMPLETIONS_URL, {
|
|
138
|
+
method: "POST",
|
|
139
|
+
headers: {
|
|
140
|
+
"Authorization": `Bearer ${apiKey}`,
|
|
141
|
+
"Content-Type": "application/json",
|
|
142
|
+
},
|
|
143
|
+
body: JSON.stringify({
|
|
144
|
+
model: selectedModel(model),
|
|
145
|
+
temperature: 0.2,
|
|
146
|
+
response_format: { type: "json_object" },
|
|
147
|
+
messages: [
|
|
148
|
+
{
|
|
149
|
+
role: "system",
|
|
150
|
+
content: [
|
|
151
|
+
"You are Flowwatch's backend reliability AI.",
|
|
152
|
+
"Use only the provided JSON context.",
|
|
153
|
+
"Do not invent workflow names, trace IDs, errors, metrics, services, or incidents.",
|
|
154
|
+
"Return valid JSON with these exact keys: summary, likelyCause, impact, evidence, recommendedActions, confidence.",
|
|
155
|
+
"evidence and recommendedActions must be arrays of strings. confidence must be a number from 0 to 100.",
|
|
156
|
+
].join(" "),
|
|
157
|
+
},
|
|
158
|
+
{
|
|
159
|
+
role: "user",
|
|
160
|
+
content: JSON.stringify(context),
|
|
161
|
+
},
|
|
162
|
+
],
|
|
163
|
+
}),
|
|
164
|
+
});
|
|
165
|
+
if (!response.ok) {
|
|
166
|
+
const message = await response.text();
|
|
167
|
+
throw new Error(`Groq insight request failed: ${response.status} ${message}`);
|
|
168
|
+
}
|
|
169
|
+
const completion = await response.json();
|
|
170
|
+
const content = completion.choices?.[0]?.message?.content;
|
|
171
|
+
if (!content) {
|
|
172
|
+
throw new Error("Groq returned an empty insight response");
|
|
173
|
+
}
|
|
174
|
+
return normalizeInsight(parseInsightJson(content), context);
|
|
175
|
+
}
|
|
176
|
+
export async function askGroqAi(context, message, history, model) {
|
|
177
|
+
if (!isServerObservabilityQuestion(message)) {
|
|
178
|
+
return outOfScopeFlowwatchResponse();
|
|
179
|
+
}
|
|
180
|
+
const apiKey = getGroqApiKey();
|
|
181
|
+
if (!apiKey) {
|
|
182
|
+
throw new Error("GROQ_API_KEY is not configured");
|
|
183
|
+
}
|
|
184
|
+
const safeHistory = sanitizeChatHistory(history);
|
|
185
|
+
const messages = [
|
|
186
|
+
{
|
|
187
|
+
role: "system",
|
|
188
|
+
content: [
|
|
189
|
+
"You are Flowwatch's backend reliability AI.",
|
|
190
|
+
"You help developers diagnose errors, traces, feature flags, workflows, and health checks.",
|
|
191
|
+
"Only answer questions about the current server, backend application, Flowwatch data, reliability, observability, or operational debugging.",
|
|
192
|
+
"If the user asks for unrelated general knowledge, personal advice, creative writing, jokes, math homework, trivia, or anything outside this server context, refuse briefly and redirect them to ask about server health, errors, traces, workflows, feature flags, or latency.",
|
|
193
|
+
"Use the provided JSON context of the system which contains recent workflows, executions, errors, traces, feature flags, and health check statuses.",
|
|
194
|
+
"Answer the user's question accurately. Focus on diagnostics, suggestions, and resolving issues.",
|
|
195
|
+
"Keep answers developer-friendly, clear, and actionable. Use markdown formatting for lists, codes, and code snippets.",
|
|
196
|
+
].join(" "),
|
|
197
|
+
},
|
|
198
|
+
{
|
|
199
|
+
role: "system",
|
|
200
|
+
content: `Here is the current system context: ${JSON.stringify(context)}`,
|
|
201
|
+
},
|
|
202
|
+
...safeHistory,
|
|
203
|
+
{
|
|
204
|
+
role: "user",
|
|
205
|
+
content: message,
|
|
206
|
+
}
|
|
207
|
+
];
|
|
208
|
+
const response = await fetch(GROQ_CHAT_COMPLETIONS_URL, {
|
|
209
|
+
method: "POST",
|
|
210
|
+
headers: {
|
|
211
|
+
"Authorization": `Bearer ${apiKey}`,
|
|
212
|
+
"Content-Type": "application/json",
|
|
213
|
+
},
|
|
214
|
+
body: JSON.stringify({
|
|
215
|
+
model: selectedModel(model),
|
|
216
|
+
temperature: 0.5,
|
|
217
|
+
messages,
|
|
218
|
+
}),
|
|
219
|
+
});
|
|
220
|
+
if (!response.ok) {
|
|
221
|
+
const msg = await response.text();
|
|
222
|
+
throw new Error(`Groq chat request failed: ${response.status} ${msg}`);
|
|
223
|
+
}
|
|
224
|
+
const completion = await response.json();
|
|
225
|
+
const content = completion.choices?.[0]?.message?.content;
|
|
226
|
+
if (!content) {
|
|
227
|
+
throw new Error("Groq returned an empty response");
|
|
228
|
+
}
|
|
229
|
+
return content;
|
|
230
|
+
}
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
import type { FlowwatchConfig } from "./types/index.js";
|
|
2
|
+
import type { RegisterWorkflow, TriggerWorkflow } from "./engine/workflows/types.js";
|
|
3
|
+
import type { EvaluateFlag } from "./engine/flags/types.js";
|
|
4
|
+
import { type TraceFunction } from "./engine/trace/traceEngine.js";
|
|
5
|
+
import { type CaptureErrorFunction } from "./engine/errors/errorEngine.js";
|
|
6
|
+
import type { ErrorRequestHandler, RequestHandler, Router } from "express";
|
|
7
|
+
export interface Flowwatch {
|
|
8
|
+
dashboard: Router;
|
|
9
|
+
workflow: RegisterWorkflow;
|
|
10
|
+
trigger: TriggerWorkflow;
|
|
11
|
+
flag: EvaluateFlag;
|
|
12
|
+
requestTracer: RequestHandler;
|
|
13
|
+
trace: TraceFunction;
|
|
14
|
+
errorHandler: ErrorRequestHandler;
|
|
15
|
+
captureError: CaptureErrorFunction;
|
|
16
|
+
}
|
|
17
|
+
export declare function createFlowwatch(config: FlowwatchConfig): Promise<Flowwatch>;
|
|
@@ -0,0 +1,90 @@
|
|
|
1
|
+
import { loadFlowwatchEnv } from "./utils/flowwatchEnvStore.js";
|
|
2
|
+
import { createDashboardRouter } from "./dashboard/routes/router.js";
|
|
3
|
+
import { validateConfig } from "./runtime/config/validationConfig.js";
|
|
4
|
+
import { normalizeConfig } from "./runtime/config/normalizeConfig.js";
|
|
5
|
+
import { createPostgresPool } from "./persistence/db/postgres.js";
|
|
6
|
+
import { createElasticsearchClient } from "./search/elasticsearch/client.js";
|
|
7
|
+
import { runMigrations } from "./persistence/migrations/migrationRunner.js";
|
|
8
|
+
import { migrations } from "./persistence/migrations/migrations.js";
|
|
9
|
+
import { createWorkflowEngine } from "./engine/workflows/workflowEngine.js";
|
|
10
|
+
import { createWorkflowQueue } from "./engine/background/queues/workflowQueue.js";
|
|
11
|
+
import { createWorkflowWorker } from "./engine/background/workers/workflowWorker.js";
|
|
12
|
+
import { createFlagEngine } from "./engine/flags/flagEngine.js";
|
|
13
|
+
import { createRequestTracingMiddleware } from "./runtime/tracing/tracingMiddleware.js";
|
|
14
|
+
import { createTraceEngine } from "./engine/trace/traceEngine.js";
|
|
15
|
+
import { captureError, createErrorHandler } from "./engine/errors/errorEngine.js";
|
|
16
|
+
import { createMissingMappings } from "./search/elasticsearch/mappingChecker.js";
|
|
17
|
+
import { createRedisClient } from "./persistence/cache/redisClient.js";
|
|
18
|
+
export async function createFlowwatch(config) {
|
|
19
|
+
await loadFlowwatchEnv();
|
|
20
|
+
const validConfig = validateConfig(config);
|
|
21
|
+
const normalizedConfig = await normalizeConfig(validConfig);
|
|
22
|
+
const postgresPool = createPostgresPool(normalizedConfig.db);
|
|
23
|
+
if (normalizedConfig.migrations.autoRun) {
|
|
24
|
+
await runMigrations(postgresPool, migrations);
|
|
25
|
+
}
|
|
26
|
+
const redisClient = createRedisClient(normalizedConfig.redis.url);
|
|
27
|
+
const elasticsearchClient = createElasticsearchClient(normalizedConfig.elasticsearch.node);
|
|
28
|
+
// BullMQ requires Redis ≥ 5. Gracefully degrade on older versions.
|
|
29
|
+
let workflowQueue = null;
|
|
30
|
+
try {
|
|
31
|
+
workflowQueue = createWorkflowQueue(normalizedConfig.redis.url);
|
|
32
|
+
// Probe the connection — BullMQ throws synchronously on version check
|
|
33
|
+
await workflowQueue.waitUntilReady();
|
|
34
|
+
}
|
|
35
|
+
catch (err) {
|
|
36
|
+
const reason = err?.message ?? String(err);
|
|
37
|
+
console.warn(`[Flowwatch] ⚠️ Workflow queue unavailable (${reason}). Workflows will be registered but cannot be executed until Redis ≥ 5 is available.`);
|
|
38
|
+
workflowQueue = null;
|
|
39
|
+
}
|
|
40
|
+
const traceEngine = createTraceEngine({
|
|
41
|
+
pool: postgresPool,
|
|
42
|
+
elasticsearchClient,
|
|
43
|
+
});
|
|
44
|
+
const workflowEngine = createWorkflowEngine({
|
|
45
|
+
pool: postgresPool,
|
|
46
|
+
workflowQueue,
|
|
47
|
+
traceEngine,
|
|
48
|
+
});
|
|
49
|
+
const requestTracer = createRequestTracingMiddleware(postgresPool);
|
|
50
|
+
const errorEngineOptions = {
|
|
51
|
+
pool: postgresPool,
|
|
52
|
+
elasticsearchClient,
|
|
53
|
+
};
|
|
54
|
+
const errorHandler = createErrorHandler(errorEngineOptions);
|
|
55
|
+
const captureFlowwatchError = (error, options) => {
|
|
56
|
+
return captureError(errorEngineOptions, error, options);
|
|
57
|
+
};
|
|
58
|
+
const flagEngine = createFlagEngine(postgresPool, traceEngine, captureFlowwatchError, redisClient);
|
|
59
|
+
await createMissingMappings(elasticsearchClient);
|
|
60
|
+
if (normalizedConfig.worker.enabled && workflowQueue !== null) {
|
|
61
|
+
try {
|
|
62
|
+
createWorkflowWorker({
|
|
63
|
+
redisUrl: normalizedConfig.redis.url,
|
|
64
|
+
pool: postgresPool,
|
|
65
|
+
getWorkflow: workflowEngine.getWorkflow,
|
|
66
|
+
traceEngine,
|
|
67
|
+
captureError: captureFlowwatchError,
|
|
68
|
+
});
|
|
69
|
+
}
|
|
70
|
+
catch (err) {
|
|
71
|
+
console.warn(`[Flowwatch] ⚠️ Workflow worker could not start: ${err?.message}`);
|
|
72
|
+
}
|
|
73
|
+
}
|
|
74
|
+
const dashboard = createDashboardRouter({
|
|
75
|
+
config: normalizedConfig,
|
|
76
|
+
postgresPool,
|
|
77
|
+
redisClient,
|
|
78
|
+
elasticsearchClient,
|
|
79
|
+
});
|
|
80
|
+
return {
|
|
81
|
+
dashboard,
|
|
82
|
+
workflow: workflowEngine.workflow,
|
|
83
|
+
trigger: workflowEngine.trigger,
|
|
84
|
+
flag: flagEngine.flag,
|
|
85
|
+
requestTracer,
|
|
86
|
+
trace: traceEngine.trace,
|
|
87
|
+
errorHandler,
|
|
88
|
+
captureError: captureFlowwatchError,
|
|
89
|
+
};
|
|
90
|
+
}
|
|
@@ -0,0 +1,204 @@
|
|
|
1
|
+
import type { NormalizedFlowwatchConfig } from "../../types/index.js";
|
|
2
|
+
export declare function serializeFlag(flag: any, ruleCount?: number): {
|
|
3
|
+
id: any;
|
|
4
|
+
key: any;
|
|
5
|
+
description: any;
|
|
6
|
+
enabled: any;
|
|
7
|
+
rollout: any;
|
|
8
|
+
rolloutPercentage: any;
|
|
9
|
+
rules: number;
|
|
10
|
+
changedBy: any;
|
|
11
|
+
createdAt: string | null;
|
|
12
|
+
updatedAt: string | null;
|
|
13
|
+
};
|
|
14
|
+
export declare function serializeRule(rule: any): {
|
|
15
|
+
id: any;
|
|
16
|
+
flagId: any;
|
|
17
|
+
attribute: any;
|
|
18
|
+
operator: any;
|
|
19
|
+
value: any;
|
|
20
|
+
enabled: any;
|
|
21
|
+
createdAt: string | null;
|
|
22
|
+
updatedAt: string | null;
|
|
23
|
+
};
|
|
24
|
+
export declare function serializeAuditLog(log: any): {
|
|
25
|
+
id: any;
|
|
26
|
+
flagId: any;
|
|
27
|
+
action: any;
|
|
28
|
+
before: any;
|
|
29
|
+
after: any;
|
|
30
|
+
changedBy: any;
|
|
31
|
+
createdAt: string | null;
|
|
32
|
+
};
|
|
33
|
+
export declare function serializeError(error: any): {
|
|
34
|
+
id: any;
|
|
35
|
+
message: any;
|
|
36
|
+
name: any;
|
|
37
|
+
category: any;
|
|
38
|
+
level: any;
|
|
39
|
+
source: any;
|
|
40
|
+
status: any;
|
|
41
|
+
statusCode: any;
|
|
42
|
+
trace: any;
|
|
43
|
+
traceId: any;
|
|
44
|
+
spanId: any;
|
|
45
|
+
fingerprint: any;
|
|
46
|
+
metadata: any;
|
|
47
|
+
stack: any;
|
|
48
|
+
occurred: string;
|
|
49
|
+
occurredAt: string | null;
|
|
50
|
+
createdAt: string | null;
|
|
51
|
+
};
|
|
52
|
+
export declare function serializeTrace(trace: any, spans?: any[]): {
|
|
53
|
+
id: any;
|
|
54
|
+
method: any;
|
|
55
|
+
path: any;
|
|
56
|
+
status: any;
|
|
57
|
+
statusCode: any;
|
|
58
|
+
ip: any;
|
|
59
|
+
duration: any;
|
|
60
|
+
durationMs: any;
|
|
61
|
+
userId: any;
|
|
62
|
+
userAgent: any;
|
|
63
|
+
metadata: any;
|
|
64
|
+
startedAt: string | null;
|
|
65
|
+
endedAt: string | null;
|
|
66
|
+
createdAt: string | null;
|
|
67
|
+
spans: {
|
|
68
|
+
id: any;
|
|
69
|
+
traceId: any;
|
|
70
|
+
parentSpanId: any;
|
|
71
|
+
name: any;
|
|
72
|
+
type: any;
|
|
73
|
+
status: string;
|
|
74
|
+
duration: any;
|
|
75
|
+
durationMs: any;
|
|
76
|
+
metadata: any;
|
|
77
|
+
startedAt: string | null;
|
|
78
|
+
endedAt: string | null;
|
|
79
|
+
}[];
|
|
80
|
+
};
|
|
81
|
+
export declare function serializeExecution(execution: any, steps?: any[]): {
|
|
82
|
+
id: any;
|
|
83
|
+
workflowId: any;
|
|
84
|
+
workflow: any;
|
|
85
|
+
workflowName: any;
|
|
86
|
+
workflowVersion: any;
|
|
87
|
+
status: any;
|
|
88
|
+
input: any;
|
|
89
|
+
output: any;
|
|
90
|
+
error: any;
|
|
91
|
+
started: string;
|
|
92
|
+
finished: string;
|
|
93
|
+
failedStep: any;
|
|
94
|
+
attempts: any;
|
|
95
|
+
duration: string;
|
|
96
|
+
createdAt: string | null;
|
|
97
|
+
startedAt: string | null;
|
|
98
|
+
completedAt: string | null;
|
|
99
|
+
failedAt: string | null;
|
|
100
|
+
durationMs: number | null;
|
|
101
|
+
steps: {
|
|
102
|
+
id: any;
|
|
103
|
+
executionId: any;
|
|
104
|
+
workflowStepId: any;
|
|
105
|
+
stepIndex: any;
|
|
106
|
+
stepName: any;
|
|
107
|
+
name: any;
|
|
108
|
+
status: any;
|
|
109
|
+
input: any;
|
|
110
|
+
output: any;
|
|
111
|
+
error: any;
|
|
112
|
+
attempts: any;
|
|
113
|
+
attemptCount: any;
|
|
114
|
+
maxRetries: any;
|
|
115
|
+
startedAt: string | null;
|
|
116
|
+
completedAt: string | null;
|
|
117
|
+
failedAt: string | null;
|
|
118
|
+
nextRetryAt: string | null;
|
|
119
|
+
durationMs: number | null;
|
|
120
|
+
duration: string;
|
|
121
|
+
}[];
|
|
122
|
+
};
|
|
123
|
+
export declare function serializeSettings(config: NormalizedFlowwatchConfig): {
|
|
124
|
+
serviceName: string;
|
|
125
|
+
environment: string;
|
|
126
|
+
dashboard: {
|
|
127
|
+
path: string;
|
|
128
|
+
enabled: boolean;
|
|
129
|
+
authEnabled: boolean;
|
|
130
|
+
};
|
|
131
|
+
worker: {
|
|
132
|
+
concurrency: number;
|
|
133
|
+
enabled: boolean;
|
|
134
|
+
workflowConcurrency: number;
|
|
135
|
+
errorIndexingConcurrency: number;
|
|
136
|
+
maintenanceConcurrency: number;
|
|
137
|
+
queuePrefix: string;
|
|
138
|
+
};
|
|
139
|
+
migrations: Required<import("../../types/index.js").FlowwatchMigrationConfig>;
|
|
140
|
+
ai: {
|
|
141
|
+
groqApiKeyConfigured: boolean;
|
|
142
|
+
groqModel: string;
|
|
143
|
+
};
|
|
144
|
+
};
|
|
145
|
+
export declare function serializeWorkflowSummary(workflow: any, executions: any[], definitionSteps: any[], latestExecution?: any, latestExecutionSteps?: any[]): {
|
|
146
|
+
id: any;
|
|
147
|
+
name: any;
|
|
148
|
+
version: any;
|
|
149
|
+
steps: number;
|
|
150
|
+
created: string;
|
|
151
|
+
createdAt: string | null;
|
|
152
|
+
updatedAt: string | null;
|
|
153
|
+
lastStatus: any;
|
|
154
|
+
totalRuns: number;
|
|
155
|
+
completedRuns: number;
|
|
156
|
+
failedRuns: number;
|
|
157
|
+
runningRuns: number;
|
|
158
|
+
failures: number;
|
|
159
|
+
pinned: boolean;
|
|
160
|
+
chain: any[];
|
|
161
|
+
latestExecution: {
|
|
162
|
+
id: any;
|
|
163
|
+
workflowId: any;
|
|
164
|
+
workflow: any;
|
|
165
|
+
workflowName: any;
|
|
166
|
+
workflowVersion: any;
|
|
167
|
+
status: any;
|
|
168
|
+
input: any;
|
|
169
|
+
output: any;
|
|
170
|
+
error: any;
|
|
171
|
+
started: string;
|
|
172
|
+
finished: string;
|
|
173
|
+
failedStep: any;
|
|
174
|
+
attempts: any;
|
|
175
|
+
duration: string;
|
|
176
|
+
createdAt: string | null;
|
|
177
|
+
startedAt: string | null;
|
|
178
|
+
completedAt: string | null;
|
|
179
|
+
failedAt: string | null;
|
|
180
|
+
durationMs: number | null;
|
|
181
|
+
steps: {
|
|
182
|
+
id: any;
|
|
183
|
+
executionId: any;
|
|
184
|
+
workflowStepId: any;
|
|
185
|
+
stepIndex: any;
|
|
186
|
+
stepName: any;
|
|
187
|
+
name: any;
|
|
188
|
+
status: any;
|
|
189
|
+
input: any;
|
|
190
|
+
output: any;
|
|
191
|
+
error: any;
|
|
192
|
+
attempts: any;
|
|
193
|
+
attemptCount: any;
|
|
194
|
+
maxRetries: any;
|
|
195
|
+
startedAt: string | null;
|
|
196
|
+
completedAt: string | null;
|
|
197
|
+
failedAt: string | null;
|
|
198
|
+
nextRetryAt: string | null;
|
|
199
|
+
durationMs: number | null;
|
|
200
|
+
duration: string;
|
|
201
|
+
}[];
|
|
202
|
+
} | undefined;
|
|
203
|
+
};
|
|
204
|
+
export declare function latestByWorkflow(executions: any[]): Map<string, any>;
|