@vreko/cli 3.0.1

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 (98) hide show
  1. package/LICENSE +201 -0
  2. package/README.md +45 -0
  3. package/dist/CeremonyView-LQS7FTMK.js +134 -0
  4. package/dist/CeremonyView-LQS7FTMK.js.map +1 -0
  5. package/dist/InitApp-7K5DTYSW.js +1479 -0
  6. package/dist/InitApp-7K5DTYSW.js.map +1 -0
  7. package/dist/SkippedTestDetector-PJSKSOZR.js +7 -0
  8. package/dist/SkippedTestDetector-PJSKSOZR.js.map +1 -0
  9. package/dist/TuiApp-FX23XQBK.js +8 -0
  10. package/dist/TuiApp-FX23XQBK.js.map +1 -0
  11. package/dist/analysis-ABEO6RTN.js +8 -0
  12. package/dist/analysis-ABEO6RTN.js.map +1 -0
  13. package/dist/auth-XNBEBNPY.js +7669 -0
  14. package/dist/auth-XNBEBNPY.js.map +1 -0
  15. package/dist/ceremony-M7CXVBVA.js +45 -0
  16. package/dist/ceremony-M7CXVBVA.js.map +1 -0
  17. package/dist/chunk-A3QSZJPD.js +3147 -0
  18. package/dist/chunk-A3QSZJPD.js.map +1 -0
  19. package/dist/chunk-ASGZ5B6C.js +3969 -0
  20. package/dist/chunk-ASGZ5B6C.js.map +1 -0
  21. package/dist/chunk-DMXC2JTC.js +58 -0
  22. package/dist/chunk-DMXC2JTC.js.map +1 -0
  23. package/dist/chunk-EEBSK2IH.js +161 -0
  24. package/dist/chunk-EEBSK2IH.js.map +1 -0
  25. package/dist/chunk-EWOJGXRX.js +22 -0
  26. package/dist/chunk-EWOJGXRX.js.map +1 -0
  27. package/dist/chunk-F7GEJLP7.js +2389 -0
  28. package/dist/chunk-F7GEJLP7.js.map +1 -0
  29. package/dist/chunk-GOYL3F4T.js +605 -0
  30. package/dist/chunk-GOYL3F4T.js.map +1 -0
  31. package/dist/chunk-GRMRYWYS.js +17 -0
  32. package/dist/chunk-GRMRYWYS.js.map +1 -0
  33. package/dist/chunk-GSUGROXB.js +1951 -0
  34. package/dist/chunk-GSUGROXB.js.map +1 -0
  35. package/dist/chunk-H7773ONB.js +50 -0
  36. package/dist/chunk-H7773ONB.js.map +1 -0
  37. package/dist/chunk-HFQHU5LC.js +445 -0
  38. package/dist/chunk-HFQHU5LC.js.map +1 -0
  39. package/dist/chunk-IVHUBLJD.js +318 -0
  40. package/dist/chunk-IVHUBLJD.js.map +1 -0
  41. package/dist/chunk-KJWKY4L4.js +14 -0
  42. package/dist/chunk-KJWKY4L4.js.map +1 -0
  43. package/dist/chunk-MJVY2XUN.js +1793 -0
  44. package/dist/chunk-MJVY2XUN.js.map +1 -0
  45. package/dist/chunk-QWZVCJII.js +1797 -0
  46. package/dist/chunk-QWZVCJII.js.map +1 -0
  47. package/dist/chunk-VTSNRV3V.js +3237 -0
  48. package/dist/chunk-VTSNRV3V.js.map +1 -0
  49. package/dist/chunk-W5B4GTXR.js +1466 -0
  50. package/dist/chunk-W5B4GTXR.js.map +1 -0
  51. package/dist/chunk-WZEZLVOW.js +4995 -0
  52. package/dist/chunk-WZEZLVOW.js.map +1 -0
  53. package/dist/chunk-YPTTIXKC.js +199 -0
  54. package/dist/chunk-YPTTIXKC.js.map +1 -0
  55. package/dist/chunk-Z55UGM6X.js +6360 -0
  56. package/dist/chunk-Z55UGM6X.js.map +1 -0
  57. package/dist/chunk-ZIIRQODJ.js +110 -0
  58. package/dist/chunk-ZIIRQODJ.js.map +1 -0
  59. package/dist/chunk-ZSUQ4FMB.js +77 -0
  60. package/dist/chunk-ZSUQ4FMB.js.map +1 -0
  61. package/dist/client-JMTSZS3V.js +10 -0
  62. package/dist/client-JMTSZS3V.js.map +1 -0
  63. package/dist/deprecated-snap.js +19 -0
  64. package/dist/deprecated-snap.js.map +1 -0
  65. package/dist/dist-2KWBZFLA.js +14 -0
  66. package/dist/dist-2KWBZFLA.js.map +1 -0
  67. package/dist/dist-5ZYKNNU3.js +7 -0
  68. package/dist/dist-5ZYKNNU3.js.map +1 -0
  69. package/dist/dist-CP3RFHPI.js +11 -0
  70. package/dist/dist-CP3RFHPI.js.map +1 -0
  71. package/dist/gecko-53ITAGG6.js +56 -0
  72. package/dist/gecko-53ITAGG6.js.map +1 -0
  73. package/dist/guards-QAFC64NO.js +7 -0
  74. package/dist/guards-QAFC64NO.js.map +1 -0
  75. package/dist/index.js +57785 -0
  76. package/dist/index.js.map +1 -0
  77. package/dist/init-command-246JIVXM.js +7 -0
  78. package/dist/init-command-246JIVXM.js.map +1 -0
  79. package/dist/init-core-KAI7LCXZ.js +12 -0
  80. package/dist/init-core-KAI7LCXZ.js.map +1 -0
  81. package/dist/init-scan-RZNYDTUV.js +1919 -0
  82. package/dist/init-scan-RZNYDTUV.js.map +1 -0
  83. package/dist/local-service-adapter-6KNN6WQL.js +8 -0
  84. package/dist/local-service-adapter-6KNN6WQL.js.map +1 -0
  85. package/dist/secure-credentials-JXWAQLS2.js +306 -0
  86. package/dist/secure-credentials-JXWAQLS2.js.map +1 -0
  87. package/dist/tui-TPJPUS2R.js +111 -0
  88. package/dist/tui-TPJPUS2R.js.map +1 -0
  89. package/dist/vreko-dir-O3RLG7PI.js +8 -0
  90. package/dist/vreko-dir-O3RLG7PI.js.map +1 -0
  91. package/package.json +132 -0
  92. package/scripts/check-banned-words.ts +152 -0
  93. package/scripts/hooks/posttooluse-file-notify.sh +108 -0
  94. package/scripts/hooks/pretooluse-fragile-guard.sh +82 -0
  95. package/scripts/post-install-notice.js +24 -0
  96. package/scripts/postinstall.mjs +84 -0
  97. package/scripts/preuninstall.mjs +34 -0
  98. package/scripts/verify-jsx-transform.mjs +55 -0
@@ -0,0 +1,3147 @@
1
+ #!/usr/bin/env node
2
+ import { logger } from './chunk-GOYL3F4T.js';
3
+ import { FEATURE_FLAGS, validateTelemetryEvent, FeatureManager } from './chunk-WZEZLVOW.js';
4
+ import { __commonJS, __name, __export } from './chunk-EWOJGXRX.js';
5
+ import { neonConfig, neon } from '@neondatabase/serverless';
6
+ import { readFileSync } from 'fs';
7
+ import { dirname, join } from 'path';
8
+ import { fileURLToPath } from 'url';
9
+ import { randomUUID, createHash } from 'crypto';
10
+ import { execFile } from 'child_process';
11
+ import { promisify } from 'util';
12
+ import { PostHog } from 'posthog-node';
13
+ import client from 'prom-client';
14
+ import { trace, metrics, context, SpanStatusCode, propagation, ROOT_CONTEXT } from '@opentelemetry/api';
15
+ import { OTLPMetricExporter } from '@opentelemetry/exporter-metrics-otlp-http';
16
+ import { OTLPTraceExporter } from '@opentelemetry/exporter-trace-otlp-http';
17
+ import { PgInstrumentation } from '@opentelemetry/instrumentation-pg';
18
+ import { PinoInstrumentation } from '@opentelemetry/instrumentation-pino';
19
+ import { resourceFromAttributes } from '@opentelemetry/resources';
20
+ import { PeriodicExportingMetricReader, MeterProvider } from '@opentelemetry/sdk-metrics';
21
+ import { BatchSpanProcessor, ConsoleSpanExporter, TraceIdRatioBasedSampler } from '@opentelemetry/sdk-trace-base';
22
+ import { NodeTracerProvider } from '@opentelemetry/sdk-trace-node';
23
+ import { ATTR_SERVICE_VERSION, ATTR_SERVICE_NAME } from '@opentelemetry/semantic-conventions';
24
+
25
+ process.env.VREKO_CLI='true';process.env.NODE_NO_WARNINGS='1';
26
+
27
+ // ../../packages/infrastructure/package.json
28
+ var require_package = __commonJS({
29
+ "../../packages/infrastructure/package.json"(exports, module) {
30
+ module.exports = {
31
+ name: "@vreko/infrastructure",
32
+ version: "0.2.0",
33
+ license: "Apache-2.0",
34
+ author: "Vreko Team",
35
+ repository: {
36
+ type: "git",
37
+ url: "https://github.com/vreko-dev.git",
38
+ directory: "packages/infrastructure"
39
+ },
40
+ files: [
41
+ "dist"
42
+ ],
43
+ dependencies: {
44
+ "@neondatabase/serverless": "catalog:",
45
+ "@opentelemetry/api": "catalog:",
46
+ "@opentelemetry/exporter-metrics-otlp-http": "catalog:",
47
+ "@opentelemetry/exporter-trace-otlp-http": "catalog:",
48
+ "@opentelemetry/instrumentation-pg": "catalog:",
49
+ "@opentelemetry/instrumentation-pino": "catalog:",
50
+ "@opentelemetry/resources": "catalog:",
51
+ "@opentelemetry/sdk-metrics": "catalog:",
52
+ "@opentelemetry/sdk-trace-base": "catalog:",
53
+ "@opentelemetry/sdk-trace-node": "catalog:",
54
+ "@opentelemetry/semantic-conventions": "catalog:",
55
+ "@vreko/contracts": "workspace:*",
56
+ bullmq: "catalog:",
57
+ nanoid: "catalog:",
58
+ pino: "catalog:",
59
+ "posthog-node": "catalog:",
60
+ opossum: "catalog:",
61
+ "p-queue": "catalog:",
62
+ "p-retry": "catalog:",
63
+ "lru-cache": "catalog:",
64
+ chokidar: "catalog:",
65
+ "prom-client": "catalog:"
66
+ },
67
+ optionalDependencies: {
68
+ "@sentry/node": "catalog:",
69
+ "@sentry/profiling-node": "catalog:"
70
+ },
71
+ devDependencies: {
72
+ "@vreko/tsconfig": "workspace:*",
73
+ "@types/node": "catalog:",
74
+ "posthog-js": "catalog:",
75
+ tsup: "catalog:",
76
+ typescript: "catalog:",
77
+ vitest: "catalog:"
78
+ },
79
+ exports: {
80
+ ".": {
81
+ types: "./dist/index.d.ts",
82
+ default: "./dist/index.js"
83
+ },
84
+ "./logging/logger": {
85
+ types: "./dist/logging/logger.d.ts",
86
+ default: "./dist/logging/logger.js"
87
+ },
88
+ "./observability": {
89
+ types: "./dist/observability/index.d.ts",
90
+ default: "./dist/observability/index.js"
91
+ },
92
+ "./observability/index": {
93
+ types: "./dist/observability/index.d.ts",
94
+ default: "./dist/observability/index.js"
95
+ },
96
+ "./observability/vocabulary": {
97
+ types: "./dist/observability/vocabulary.d.ts",
98
+ default: "./dist/observability/vocabulary.js"
99
+ },
100
+ "./observability/wrapper": {
101
+ types: "./dist/observability/wrapper.d.ts",
102
+ default: "./dist/observability/wrapper.js"
103
+ },
104
+ "./observability/retro-queries": {
105
+ types: "./dist/observability/retro-queries.d.ts",
106
+ default: "./dist/observability/retro-queries.js"
107
+ },
108
+ "./metrics": {
109
+ types: "./dist/metrics/index.d.ts",
110
+ default: "./dist/metrics/index.js"
111
+ },
112
+ "./tracing": {
113
+ types: "./dist/tracing/index.d.ts",
114
+ default: "./dist/tracing/index.js"
115
+ },
116
+ "./health": {
117
+ types: "./dist/health/index.d.ts",
118
+ default: "./dist/health/index.js"
119
+ },
120
+ "./resiliency": {
121
+ types: "./dist/resiliency/index.d.ts",
122
+ default: "./dist/resiliency/index.js"
123
+ },
124
+ "./cache": {
125
+ types: "./dist/cache/index.d.ts",
126
+ default: "./dist/cache/index.js"
127
+ },
128
+ "./files": {
129
+ types: "./dist/files/watcher.d.ts",
130
+ default: "./dist/files/watcher.js"
131
+ },
132
+ "./sqlite": {
133
+ types: "./dist/sqlite/index.d.ts",
134
+ default: "./dist/sqlite/index.js"
135
+ },
136
+ "./neon": {
137
+ types: "./dist/neon/index.d.ts",
138
+ default: "./dist/neon/index.js"
139
+ },
140
+ "./prometheus": {
141
+ types: "./dist/prometheus/index.d.ts",
142
+ default: "./dist/prometheus/index.js"
143
+ },
144
+ "./queue/email-queue-service": {
145
+ types: "./dist/queue/email-queue-service.d.ts",
146
+ default: "./dist/queue/email-queue-service.js"
147
+ },
148
+ "./queue/flywheel-queue-service": {
149
+ types: "./dist/queue/flywheel-queue-service.d.ts",
150
+ default: "./dist/queue/flywheel-queue-service.js"
151
+ },
152
+ "./sentry": {
153
+ types: "./dist/sentry/index.d.ts",
154
+ default: "./dist/sentry/index.js"
155
+ }
156
+ },
157
+ publishConfig: {
158
+ exports: {
159
+ ".": {
160
+ types: "./dist/logging/logger.d.ts",
161
+ default: "./dist/logging/logger.js"
162
+ },
163
+ "./logging/logger": {
164
+ types: "./dist/logging/logger.d.ts",
165
+ default: "./dist/logging/logger.js"
166
+ },
167
+ "./observability": {
168
+ types: "./dist/observability/index.d.ts",
169
+ default: "./dist/observability/index.js"
170
+ },
171
+ "./observability/index": {
172
+ types: "./dist/observability/index.d.ts",
173
+ default: "./dist/observability/index.js"
174
+ },
175
+ "./observability/vocabulary": {
176
+ types: "./dist/observability/vocabulary.d.ts",
177
+ default: "./dist/observability/vocabulary.js"
178
+ },
179
+ "./observability/wrapper": {
180
+ types: "./dist/observability/wrapper.d.ts",
181
+ default: "./dist/observability/wrapper.js"
182
+ },
183
+ "./observability/retro-queries": {
184
+ types: "./dist/observability/retro-queries.d.ts",
185
+ default: "./dist/observability/retro-queries.js"
186
+ },
187
+ "./health": {
188
+ types: "./dist/health/index.d.ts",
189
+ default: "./dist/health/index.js"
190
+ },
191
+ "./tracing": {
192
+ types: "./dist/tracing/index.d.ts",
193
+ default: "./dist/tracing/index.js"
194
+ },
195
+ "./metrics": {
196
+ types: "./dist/metrics/index.d.ts",
197
+ default: "./dist/metrics/index.js"
198
+ },
199
+ "./resiliency": {
200
+ types: "./dist/resiliency/index.d.ts",
201
+ default: "./dist/resiliency/index.js"
202
+ },
203
+ "./cache": {
204
+ types: "./dist/cache/index.d.ts",
205
+ default: "./dist/cache/index.js"
206
+ },
207
+ "./files": {
208
+ types: "./dist/files/watcher.d.ts",
209
+ default: "./dist/files/watcher.js"
210
+ },
211
+ "./sqlite": {
212
+ types: "./dist/sqlite/index.d.ts",
213
+ default: "./dist/sqlite/index.js"
214
+ },
215
+ "./neon": {
216
+ types: "./dist/neon/index.d.ts",
217
+ default: "./dist/neon/index.js"
218
+ },
219
+ "./queue/email-queue-service": {
220
+ types: "./dist/queue/email-queue-service.d.ts",
221
+ default: "./dist/queue/email-queue-service.js"
222
+ },
223
+ "./queue/flywheel-queue-service": {
224
+ types: "./dist/queue/flywheel-queue-service.d.ts",
225
+ default: "./dist/queue/flywheel-queue-service.js"
226
+ },
227
+ "./sentry": {
228
+ types: "./dist/sentry/index.d.ts",
229
+ default: "./dist/sentry/index.js"
230
+ }
231
+ }
232
+ },
233
+ main: "dist/index.js",
234
+ private: true,
235
+ scripts: {
236
+ build: "tsup --no-dts && tsc --build tsconfig.build.json --force && node ../../scripts/build-utils/add-js-extensions.mjs",
237
+ "build:docker": "tsup --no-dts && node ../../scripts/build-utils/add-js-extensions.mjs",
238
+ dev: "tsup --watch",
239
+ check: "biome check .",
240
+ format: "biome format --write .",
241
+ lint: "biome lint .",
242
+ "lint:fix": "biome lint --fix .",
243
+ postbuild: "test -f dist/index.d.ts && node scripts/patch-dts.cjs || echo 'Warning: Type declarations not fully generated'",
244
+ test: "vitest run",
245
+ "test:coverage": "vitest run --coverage",
246
+ "test:watch": "vitest",
247
+ "type-check": "tsc --noEmit"
248
+ },
249
+ type: "module",
250
+ types: "dist/index.d.ts"
251
+ };
252
+ }
253
+ });
254
+
255
+ // ../../packages/infrastructure/dist/environment/index.js
256
+ function isDevelopment() {
257
+ return getDeploymentEnv() === "development";
258
+ }
259
+ __name(isDevelopment, "isDevelopment");
260
+ function isProduction() {
261
+ return getDeploymentEnv() === "production";
262
+ }
263
+ __name(isProduction, "isProduction");
264
+ function getDeploymentEnv() {
265
+ const explicitEnv = process.env.DEPLOYMENT_ENV;
266
+ if (explicitEnv === "development" || explicitEnv === "staging" || explicitEnv === "production") {
267
+ return explicitEnv;
268
+ }
269
+ if (process.env.VERCEL || process.env.VERCEL_ENV || process.env.FLY_ALLOC_ID) {
270
+ return "production";
271
+ }
272
+ const authUrl = process.env.BETTER_AUTH_URL || process.env.APP_URL || "";
273
+ if (authUrl.includes("localhost") || authUrl.includes("127.0.0.1")) {
274
+ return "development";
275
+ }
276
+ if (typeof window !== "undefined") {
277
+ const hostname = window.location.hostname;
278
+ if (hostname === "localhost" || hostname === "127.0.0.1" || hostname.endsWith(".local") || hostname.endsWith(".test")) {
279
+ return "development";
280
+ }
281
+ }
282
+ if (process.env.CI) {
283
+ return "production";
284
+ }
285
+ return "production";
286
+ }
287
+ __name(getDeploymentEnv, "getDeploymentEnv");
288
+ function getAnalyticsEnv() {
289
+ return getDeploymentEnv() === "development" ? "dev" : "prod";
290
+ }
291
+ __name(getAnalyticsEnv, "getAnalyticsEnv");
292
+ function getEnvironmentInfo() {
293
+ const deployment = getDeploymentEnv();
294
+ return {
295
+ deployment,
296
+ analytics: deployment === "development" ? "dev" : "prod",
297
+ nodeEnv: process.env.NODE_ENV,
298
+ isCi: !!process.env.CI,
299
+ isVercel: !!(process.env.VERCEL || process.env.VERCEL_ENV),
300
+ isFly: !!process.env.FLY_ALLOC_ID,
301
+ isLocalhost: (process.env.BETTER_AUTH_URL?.includes("localhost") ?? false) || typeof window !== "undefined" && (window.location.hostname === "localhost" || window.location.hostname === "127.0.0.1")
302
+ };
303
+ }
304
+ __name(getEnvironmentInfo, "getEnvironmentInfo");
305
+ function detectSurface() {
306
+ if (process.env.VSCODE_EXTENSION || typeof process.env.VSCODE_PID !== "undefined") {
307
+ return "vscode";
308
+ }
309
+ if (process.env.VREKO_CLI || process.argv[1]?.includes("cli")) {
310
+ return "cli";
311
+ }
312
+ if (process.env.MCP_SERVER || process.env.MCP_MODE) {
313
+ return "mcp";
314
+ }
315
+ if (process.env.DAEMON_MODE || process.env.LOCAL_SERVICE) {
316
+ return "daemon";
317
+ }
318
+ if (process.env.API_SERVER || typeof process.env.PORT !== "undefined") {
319
+ return "api";
320
+ }
321
+ if (typeof window !== "undefined") {
322
+ return "web";
323
+ }
324
+ return "api";
325
+ }
326
+ __name(detectSurface, "detectSurface");
327
+ function getAnalyticsSuperProperties(surface) {
328
+ return {
329
+ env: getAnalyticsEnv(),
330
+ surface: surface ?? detectSurface()
331
+ };
332
+ }
333
+ __name(getAnalyticsSuperProperties, "getAnalyticsSuperProperties");
334
+
335
+ // ../../packages/infrastructure/dist/graceful-shutdown/index.js
336
+ function createGracefulShutdown(options) {
337
+ const { logger: logger2, timeoutMs = 25e3, healthMarkerPath } = options;
338
+ const cleanupHandlers = [];
339
+ let isShuttingDown = false;
340
+ let isReady = false;
341
+ function updateReadiness(ready) {
342
+ isReady = ready;
343
+ if (healthMarkerPath) {
344
+ try {
345
+ if (ready) {
346
+ globalThis.Bun?.write?.(healthMarkerPath, process.pid.toString());
347
+ } else {
348
+ globalThis.Bun?.write?.(healthMarkerPath, "");
349
+ }
350
+ } catch (error) {
351
+ logger2.debug("Health marker file operation failed", {
352
+ error
353
+ });
354
+ }
355
+ }
356
+ }
357
+ __name(updateReadiness, "updateReadiness");
358
+ async function shutdown(signal) {
359
+ if (isShuttingDown) {
360
+ logger2.warn("Shutdown already in progress, ignoring signal", {
361
+ signal
362
+ });
363
+ return;
364
+ }
365
+ isShuttingDown = true;
366
+ logger2.info("Shutdown initiated", {
367
+ signal,
368
+ pid: process.pid
369
+ });
370
+ updateReadiness(false);
371
+ logger2.info("Service marked as not ready, stopping new traffic");
372
+ const drainTimeout = Math.min(5e3, timeoutMs / 5);
373
+ logger2.info("Waiting for in-flight requests to complete", {
374
+ drainTimeoutMs: drainTimeout
375
+ });
376
+ await new Promise((resolve) => setTimeout(resolve, drainTimeout));
377
+ logger2.info("Running cleanup handlers", {
378
+ count: cleanupHandlers.length
379
+ });
380
+ const cleanupTimeout = timeoutMs - drainTimeout - 2e3;
381
+ const cleanupStart = Date.now();
382
+ for (let i = cleanupHandlers.length - 1; i >= 0; i--) {
383
+ const remainingTime = cleanupTimeout - (Date.now() - cleanupStart);
384
+ if (remainingTime <= 0) {
385
+ logger2.warn("Cleanup timeout reached, some handlers may not have completed");
386
+ break;
387
+ }
388
+ try {
389
+ const handler = cleanupHandlers[i];
390
+ const handlerTimeout = Math.min(remainingTime, 5e3);
391
+ await Promise.race([
392
+ handler(),
393
+ new Promise((_, reject) => setTimeout(() => reject(new Error("Handler timeout")), handlerTimeout))
394
+ ]);
395
+ } catch (error) {
396
+ logger2.error("Cleanup handler error", {
397
+ error,
398
+ handlerIndex: i
399
+ });
400
+ }
401
+ }
402
+ logger2.info("Shutdown complete", {
403
+ durationMs: Date.now() - cleanupStart + drainTimeout
404
+ });
405
+ process.exit(0);
406
+ }
407
+ __name(shutdown, "shutdown");
408
+ const forceExit = /* @__PURE__ */ __name(() => {
409
+ logger2.error("Forced exit due to timeout", {
410
+ timeoutMs
411
+ });
412
+ process.exit(1);
413
+ }, "forceExit");
414
+ return {
415
+ register(handler) {
416
+ cleanupHandlers.push(handler);
417
+ },
418
+ setReady() {
419
+ updateReadiness(true);
420
+ },
421
+ setNotReady() {
422
+ updateReadiness(false);
423
+ },
424
+ init() {
425
+ const handleShutdown = /* @__PURE__ */ __name((signal) => {
426
+ shutdown(signal).catch((error) => {
427
+ logger2.error("Shutdown error", {
428
+ error
429
+ });
430
+ process.exit(1);
431
+ });
432
+ setTimeout(forceExit, timeoutMs);
433
+ }, "handleShutdown");
434
+ process.on("SIGTERM", () => handleShutdown("SIGTERM"));
435
+ process.on("SIGINT", () => handleShutdown("SIGINT"));
436
+ process.on("uncaughtException", (error) => {
437
+ logger2.error("Uncaught exception, initiating shutdown", {
438
+ error
439
+ });
440
+ handleShutdown("uncaughtException");
441
+ });
442
+ process.on("unhandledRejection", (reason) => {
443
+ logger2.error("Unhandled rejection, initiating shutdown", {
444
+ reason
445
+ });
446
+ if (process.env.NODE_ENV !== "production") {
447
+ handleShutdown("unhandledRejection");
448
+ }
449
+ });
450
+ logger2.info("Graceful shutdown handler initialized", {
451
+ timeoutMs
452
+ });
453
+ },
454
+ isReady() {
455
+ return isReady;
456
+ },
457
+ isShuttingDown() {
458
+ return isShuttingDown;
459
+ }
460
+ };
461
+ }
462
+ __name(createGracefulShutdown, "createGracefulShutdown");
463
+ async function drainAndCloseServer(server, logger2) {
464
+ logger2.info("Closing server...");
465
+ const closePromise = server.close();
466
+ if (server.closeIdleConnections) {
467
+ logger2.info("Closing idle connections...");
468
+ server.closeIdleConnections();
469
+ }
470
+ const timeout = 1e4;
471
+ await Promise.race([
472
+ closePromise,
473
+ new Promise((resolve) => setTimeout(resolve, timeout))
474
+ ]);
475
+ if (server.closeAllConnections) {
476
+ logger2.info("Force closing remaining connections...");
477
+ server.closeAllConnections();
478
+ }
479
+ logger2.info("Server closed");
480
+ }
481
+ __name(drainAndCloseServer, "drainAndCloseServer");
482
+ async function preStopDelay(ms = 5e3) {
483
+ await new Promise((resolve) => setTimeout(resolve, ms));
484
+ }
485
+ __name(preStopDelay, "preStopDelay");
486
+
487
+ // ../../packages/infrastructure/dist/health/index.js
488
+ function createHealthCheck(options) {
489
+ return async () => {
490
+ const checks = {};
491
+ checks.system = {
492
+ status: "healthy",
493
+ timestamp: (/* @__PURE__ */ new Date()).toISOString(),
494
+ latency: 0
495
+ };
496
+ const memoryUsage = process.memoryUsage();
497
+ checks.memory = {
498
+ status: memoryUsage.heapUsed < 0.8 * memoryUsage.heapTotal ? "healthy" : "degraded",
499
+ message: `Memory usage: ${Math.round(memoryUsage.heapUsed / 1024 / 1024 * 100) / 100} MB`,
500
+ timestamp: (/* @__PURE__ */ new Date()).toISOString()
501
+ };
502
+ const uptime = process.uptime();
503
+ if (options.dependencies) {
504
+ for (const dep of options.dependencies) {
505
+ try {
506
+ const depStartTime = Date.now();
507
+ const result = await dep.check();
508
+ const latency = Date.now() - depStartTime;
509
+ checks[dep.name] = {
510
+ status: result.status,
511
+ message: result.message,
512
+ latency,
513
+ timestamp: (/* @__PURE__ */ new Date()).toISOString()
514
+ };
515
+ } catch (error) {
516
+ checks[dep.name] = {
517
+ status: "unhealthy",
518
+ message: error instanceof Error ? error.message : "Unknown error",
519
+ timestamp: (/* @__PURE__ */ new Date()).toISOString()
520
+ };
521
+ }
522
+ }
523
+ }
524
+ let overallStatus = "healthy";
525
+ for (const check of Object.values(checks)) {
526
+ if (check.status === "unhealthy") {
527
+ overallStatus = "unhealthy";
528
+ break;
529
+ }
530
+ if (check.status === "degraded" && overallStatus === "healthy") {
531
+ overallStatus = "degraded";
532
+ }
533
+ }
534
+ const response = {
535
+ status: overallStatus,
536
+ timestamp: (/* @__PURE__ */ new Date()).toISOString(),
537
+ service: options.service,
538
+ checks,
539
+ uptime,
540
+ memoryUsage: {
541
+ heapUsed: memoryUsage.heapUsed,
542
+ heapTotal: memoryUsage.heapTotal,
543
+ rss: memoryUsage.rss
544
+ }
545
+ };
546
+ if (options.version) {
547
+ response.version = options.version;
548
+ }
549
+ return response;
550
+ };
551
+ }
552
+ __name(createHealthCheck, "createHealthCheck");
553
+ async function checkDatabaseConnection(_connectionString) {
554
+ try {
555
+ const startTime = Date.now();
556
+ await new Promise((resolve) => setTimeout(resolve, Math.random() * 50));
557
+ const latency = Date.now() - startTime;
558
+ if (latency > 1e3) {
559
+ return {
560
+ status: "degraded",
561
+ message: `Database connection is slow (${latency}ms)`
562
+ };
563
+ }
564
+ return {
565
+ status: "healthy",
566
+ message: `Database connection successful (${latency}ms)`
567
+ };
568
+ } catch (error) {
569
+ return {
570
+ status: "unhealthy",
571
+ message: error instanceof Error ? error.message : "Database connection failed"
572
+ };
573
+ }
574
+ }
575
+ __name(checkDatabaseConnection, "checkDatabaseConnection");
576
+ async function checkRedisConnection(_redisUrl) {
577
+ try {
578
+ const startTime = Date.now();
579
+ await new Promise((resolve) => setTimeout(resolve, Math.random() * 30));
580
+ const latency = Date.now() - startTime;
581
+ if (latency > 200) {
582
+ return {
583
+ status: "degraded",
584
+ message: `Redis connection is slow (${latency}ms)`
585
+ };
586
+ }
587
+ return {
588
+ status: "healthy",
589
+ message: `Redis connection successful (${latency}ms)`
590
+ };
591
+ } catch (error) {
592
+ return {
593
+ status: "unhealthy",
594
+ message: error instanceof Error ? error.message : "Redis connection failed"
595
+ };
596
+ }
597
+ }
598
+ __name(checkRedisConnection, "checkRedisConnection");
599
+ async function checkHttpService(_url) {
600
+ try {
601
+ const startTime = Date.now();
602
+ await new Promise((resolve) => setTimeout(resolve, Math.random() * 100));
603
+ const latency = Date.now() - startTime;
604
+ if (latency > 1e3) {
605
+ return {
606
+ status: "degraded",
607
+ message: `HTTP service is slow (${latency}ms)`
608
+ };
609
+ }
610
+ return {
611
+ status: "healthy",
612
+ message: `HTTP service check successful (${latency}ms)`
613
+ };
614
+ } catch (error) {
615
+ return {
616
+ status: "unhealthy",
617
+ message: error instanceof Error ? error.message : "HTTP service check failed"
618
+ };
619
+ }
620
+ }
621
+ __name(checkHttpService, "checkHttpService");
622
+
623
+ // ../../packages/infrastructure/dist/metrics/core/events.js
624
+ var AnalyticsEvents = {
625
+ // ===== Authentication Events (6) =====
626
+ AUTH_SIGNUP_COMPLETED: "auth_signup_completed",
627
+ AUTH_LOGIN_COMPLETED: "auth_login_completed",
628
+ AUTH_LOGOUT_COMPLETED: "auth_logout_completed",
629
+ AUTH_EMAIL_VERIFIED: "auth_email_verified",
630
+ AUTH_PASSWORD_RESET_REQUESTED: "auth_password_reset_requested",
631
+ AUTH_PASSWORD_RESET_COMPLETED: "auth_password_reset_completed",
632
+ // ===== Snapshot Events (20) =====
633
+ SNAPSHOT_CREATED: "snapshot_created",
634
+ SNAPSHOT_RESTORED: "snapshot_restored",
635
+ SNAPSHOT_DELETED: "snapshot_deleted",
636
+ SNAPSHOT_SEARCHED: "snapshot_searched",
637
+ SNAPSHOT_LIMIT_HIT: "snapshot_limit_hit",
638
+ SNAPSHOT_AUTO_CREATED: "snapshot_auto_created",
639
+ SNAPSHOT_SHARED: "snapshot_shared",
640
+ SNAPSHOT_EXPORTED: "snapshot_exported",
641
+ SNAPSHOT_VIEWED: "snapshot_viewed",
642
+ SNAPSHOT_DIFF_VIEWED: "snapshot_diff_viewed",
643
+ // Removed duplicate snapshot_checkpoint_* events to maintain consistent terminology
644
+ // ===== Billing/Monetization Events (12) =====
645
+ BILLING_UPGRADE_PROMPT_SHOWN: "billing_upgrade_prompt_shown",
646
+ BILLING_UPGRADE_PROMPT_CLICKED: "billing_upgrade_prompt_clicked",
647
+ BILLING_PRICING_VIEWED: "billing_pricing_viewed",
648
+ BILLING_CHECKOUT_STARTED: "billing_checkout_started",
649
+ BILLING_CHECKOUT_COMPLETED: "billing_checkout_completed",
650
+ BILLING_CHECKOUT_ABANDONED: "billing_checkout_abandoned",
651
+ BILLING_SUBSCRIPTION_UPGRADED: "billing_subscription_upgraded",
652
+ BILLING_SUBSCRIPTION_DOWNGRADED: "billing_subscription_downgraded",
653
+ BILLING_SUBSCRIPTION_CANCELLED: "billing_subscription_cancelled",
654
+ BILLING_PAYMENT_FAILED: "billing_payment_failed",
655
+ BILLING_COUPON_APPLIED: "billing_coupon_applied",
656
+ BILLING_INVOICE_VIEWED: "billing_invoice_viewed",
657
+ // ===== Extension Events (8) =====
658
+ EXTENSION_INSTALLED: "extension_installed",
659
+ EXTENSION_ACTIVATED: "extension_activated",
660
+ EXTENSION_COMMAND_USED: "extension_command_used",
661
+ EXTENSION_SETTINGS_CHANGED: "extension_settings_changed",
662
+ EXTENSION_ERROR_OCCURRED: "extension_error_occurred",
663
+ EXTENSION_UPDATED: "extension_updated",
664
+ EXTENSION_UNINSTALLED: "extension_uninstalled",
665
+ EXTENSION_FEEDBACK_SUBMITTED: "extension_feedback_submitted",
666
+ // ===== Dashboard Events (8) =====
667
+ DASHBOARD_VIEWED: "dashboard_viewed",
668
+ DASHBOARD_API_KEY_CREATED: "dashboard_api_key_created",
669
+ DASHBOARD_API_KEY_REVOKED: "dashboard_api_key_revoked",
670
+ DASHBOARD_USAGE_CHART_VIEWED: "dashboard_usage_chart_viewed",
671
+ DASHBOARD_SETTINGS_UPDATED: "dashboard_settings_updated",
672
+ DASHBOARD_SEARCH_PERFORMED: "dashboard_search_performed",
673
+ DASHBOARD_EXPORT_TRIGGERED: "dashboard_export_triggered",
674
+ DASHBOARD_HELP_ACCESSED: "dashboard_help_accessed",
675
+ // ===== Team Collaboration Events (6) =====
676
+ TEAM_CREATED: "team_created",
677
+ TEAM_MEMBER_INVITED: "team_member_invited",
678
+ TEAM_MEMBER_JOINED: "team_member_joined",
679
+ TEAM_SNAPSHOT_SHARED: "team_snapshot_shared",
680
+ TEAM_SETTINGS_CHANGED: "team_settings_changed",
681
+ TEAM_MEMBER_REMOVED: "team_member_removed",
682
+ // ===== AI Features Events (5) =====
683
+ AI_SUGGESTION_SHOWN: "ai_suggestion_shown",
684
+ AI_SUGGESTION_ACCEPTED: "ai_suggestion_accepted",
685
+ AI_SUGGESTION_REJECTED: "ai_suggestion_rejected",
686
+ AI_RISK_DETECTED: "ai_risk_detected",
687
+ AI_RISK_PREVENTED: "ai_risk_prevented",
688
+ // ===== API Usage Events (5) =====
689
+ API_CALL_MADE: "api_call_made",
690
+ API_RATE_LIMIT_HIT: "api_rate_limit_hit",
691
+ API_ERROR_OCCURRED: "api_error_occurred",
692
+ API_KEY_ROTATED: "api_key_rotated",
693
+ API_WEBHOOK_CONFIGURED: "api_webhook_configured",
694
+ // ===== Intelligence Layer: Prediction & Learning (6) =====
695
+ PREDICTION_MADE: "prediction_made",
696
+ PREDICTION_OUTCOME_RECORDED: "prediction_outcome_recorded",
697
+ TRUST_SCORE_UPDATED: "trust_score_updated",
698
+ PATTERN_DETECTED: "pattern_detected",
699
+ PATTERN_CONFIRMED: "pattern_confirmed",
700
+ MODEL_CALIBRATION_TRIGGERED: "model_calibration_triggered",
701
+ // ===== Intelligence Layer: Cross-Repo Intelligence (4) =====
702
+ WORKSPACE_CONNECTED: "workspace_connected",
703
+ CROSS_REPO_PATTERN_DETECTED: "cross_repo_pattern_detected",
704
+ REPO_PERSONALITY_UPDATED: "repo_personality_updated",
705
+ GLOBAL_INSIGHT_APPLIED: "global_insight_applied",
706
+ // ===== Intelligence Layer: GitHub Integration (5) =====
707
+ GITHUB_REPO_CONNECTED: "github_repo_connected",
708
+ GITHUB_PR_ANALYZED: "github_pr_analyzed",
709
+ GITHUB_COMMIT_SCANNED: "github_commit_scanned",
710
+ GITHUB_AI_CONTRIBUTION_DETECTED: "github_ai_contribution_detected",
711
+ GITHUB_CHECK_POSTED: "github_check_posted",
712
+ // ===== Intelligence Layer: MCP Tools (3) =====
713
+ MCP_TOOL_CALLED: "mcp_tool_called",
714
+ MCP_CONTEXT_PROVIDED: "mcp_context_provided",
715
+ MCP_AGENT_SELF_CHECK: "mcp_agent_self_check",
716
+ // ===== Intelligence Layer: Community & Engagement (6) =====
717
+ DISASTER_STORY_SHARED: "disaster_story_shared",
718
+ FEEDBACK_SUBMITTED: "feedback_submitted",
719
+ COMMUNITY_ACTION_COMPLETED: "community_action_completed",
720
+ BETA_ELIGIBILITY_CALCULATED: "beta_eligibility_calculated",
721
+ REFERRAL_LINK_GENERATED: "referral_link_generated",
722
+ REFERRAL_CONVERTED: "referral_converted",
723
+ // ===== Activation Funnel Events (2) =====
724
+ AUTH_COMPLETED: "auth_completed",
725
+ FIRST_SNAPSHOT_CREATED: "first_snapshot_created"
726
+ };
727
+
728
+ // ../../packages/infrastructure/dist/neon/index.js
729
+ var neon_exports = {};
730
+ __export(neon_exports, {
731
+ NeonDocClient: () => NeonDocClient,
732
+ runMigration: () => runMigration,
733
+ verifySchema: () => verifySchema
734
+ });
735
+ var NeonDocClient = class {
736
+ static {
737
+ __name(this, "NeonDocClient");
738
+ }
739
+ sql;
740
+ constructor(config) {
741
+ if (config.enableCache !== false) {
742
+ neonConfig.fetchConnectionCache = true;
743
+ }
744
+ this.sql = neon(config.connectionString);
745
+ }
746
+ /**
747
+ * Execute hybrid search against doc_embeddings
748
+ *
749
+ * @param queryEmbedding - 768-dim vector from text-embedding-3-small
750
+ * @param options - Search filters and limits
751
+ * @returns Ranked search results with similarity scores
752
+ */
753
+ async hybridSearch(queryEmbedding, options = {}) {
754
+ if (queryEmbedding.length !== 768) {
755
+ throw new Error(`Expected 768-dim embedding, got ${queryEmbedding.length}`);
756
+ }
757
+ const { library = null, version = null, limit = 5, similarityThreshold = 0.75 } = options;
758
+ const embeddingStr = `[${queryEmbedding.join(",")}]`;
759
+ const results = await this.sql`
760
+ SELECT * FROM hybrid_search(
761
+ ${embeddingStr}::vector(768),
762
+ ${library},
763
+ ${version},
764
+ ${limit},
765
+ ${similarityThreshold}
766
+ )
767
+ `;
768
+ return results;
769
+ }
770
+ /**
771
+ * Insert a single doc embedding
772
+ *
773
+ * @param doc - Document embedding record
774
+ * @returns Inserted record ID
775
+ */
776
+ async insertDoc(doc) {
777
+ if (doc.embedding.length !== 768) {
778
+ throw new Error(`Expected 768-dim embedding, got ${doc.embedding.length}`);
779
+ }
780
+ const embeddingStr = `[${doc.embedding.join(",")}]`;
781
+ const result = await this.sql`
782
+ INSERT INTO doc_embeddings (library, version, doc_type, chunk_text, embedding, metadata, source_url)
783
+ VALUES (
784
+ ${doc.library},
785
+ ${doc.version},
786
+ ${doc.doc_type},
787
+ ${doc.chunk_text},
788
+ ${embeddingStr}::vector(768),
789
+ ${JSON.stringify(doc.metadata)},
790
+ ${doc.source_url}
791
+ )
792
+ ON CONFLICT (library, version, chunk_text)
793
+ DO UPDATE SET
794
+ embedding = EXCLUDED.embedding,
795
+ metadata = EXCLUDED.metadata,
796
+ indexed_at = NOW()
797
+ RETURNING id
798
+ `;
799
+ return result[0]?.id ?? "";
800
+ }
801
+ /**
802
+ * Batch insert doc embeddings (optimized for bulk ingestion)
803
+ *
804
+ * @param docs - Array of document embeddings
805
+ * @returns Count of inserted/updated records
806
+ */
807
+ async batchInsertDocs(docs) {
808
+ if (docs.length === 0) {
809
+ return 0;
810
+ }
811
+ for (const doc of docs) {
812
+ if (doc.embedding.length !== 768) {
813
+ throw new Error(`Expected 768-dim embedding, got ${doc.embedding.length}`);
814
+ }
815
+ }
816
+ let count = 0;
817
+ for (const doc of docs) {
818
+ await this.insertDoc(doc);
819
+ count++;
820
+ }
821
+ return count;
822
+ }
823
+ /**
824
+ * Get embedding stats (total chunks, by library, etc.)
825
+ */
826
+ async getStats() {
827
+ const totalResult = await this.sql`SELECT COUNT(*) as count FROM doc_embeddings`;
828
+ const total = Number(totalResult[0]?.count ?? 0);
829
+ const byLibraryResult = await this.sql`
830
+ SELECT library, COUNT(*) as count
831
+ FROM doc_embeddings
832
+ GROUP BY library
833
+ `;
834
+ const byDocTypeResult = await this.sql`
835
+ SELECT doc_type, COUNT(*) as count
836
+ FROM doc_embeddings
837
+ GROUP BY doc_type
838
+ `;
839
+ return {
840
+ total,
841
+ byLibrary: Object.fromEntries(byLibraryResult.map((r) => [
842
+ r.library,
843
+ Number(r.count)
844
+ ])),
845
+ byDocType: Object.fromEntries(byDocTypeResult.map((r) => [
846
+ r.doc_type,
847
+ Number(r.count)
848
+ ]))
849
+ };
850
+ }
851
+ };
852
+ var __filename$1 = fileURLToPath(import.meta.url);
853
+ var __dirname$1 = dirname(__filename$1);
854
+ async function runMigration(connectionString) {
855
+ try {
856
+ const sql = neon(connectionString);
857
+ const schemaPath = join(__dirname$1, "schema.sql");
858
+ const schemaSql = readFileSync(schemaPath, "utf-8");
859
+ await sql(schemaSql);
860
+ return {
861
+ success: true
862
+ };
863
+ } catch (error) {
864
+ return {
865
+ success: false,
866
+ error: error instanceof Error ? error.message : String(error)
867
+ };
868
+ }
869
+ }
870
+ __name(runMigration, "runMigration");
871
+ async function verifySchema(connectionString) {
872
+ try {
873
+ const sql = neon(connectionString);
874
+ const tableCheck = await sql`
875
+ SELECT EXISTS (
876
+ SELECT FROM information_schema.tables
877
+ WHERE table_name = 'doc_embeddings'
878
+ ) as exists
879
+ `;
880
+ const tableExists = tableCheck[0]?.exists === true;
881
+ const indexCheck = await sql`
882
+ SELECT EXISTS (
883
+ SELECT FROM pg_indexes
884
+ WHERE indexname = 'doc_embeddings_hnsw_idx'
885
+ ) as exists
886
+ `;
887
+ const hnswIndexExists = indexCheck[0]?.exists === true;
888
+ const functionCheck = await sql`
889
+ SELECT EXISTS (
890
+ SELECT FROM pg_proc
891
+ WHERE proname = 'hybrid_search'
892
+ ) as exists
893
+ `;
894
+ const hybridSearchFunctionExists = functionCheck[0]?.exists === true;
895
+ const valid = tableExists && hnswIndexExists && hybridSearchFunctionExists;
896
+ return {
897
+ valid,
898
+ checks: {
899
+ tableExists,
900
+ hnswIndexExists,
901
+ hybridSearchFunctionExists
902
+ }
903
+ };
904
+ } catch (error) {
905
+ return {
906
+ valid: false,
907
+ checks: {
908
+ tableExists: false,
909
+ hnswIndexExists: false,
910
+ hybridSearchFunctionExists: false
911
+ },
912
+ error: error instanceof Error ? error.message : String(error)
913
+ };
914
+ }
915
+ }
916
+ __name(verifySchema, "verifySchema");
917
+
918
+ // ../../packages/infrastructure/dist/observability/vocabulary.js
919
+ var AgentAction;
920
+ (function(AgentAction2) {
921
+ AgentAction2["SEARCH"] = "SEARCH";
922
+ AgentAction2["READ_FILE"] = "READ_FILE";
923
+ AgentAction2["LIST_DIR"] = "LIST_DIR";
924
+ AgentAction2["GREP"] = "GREP";
925
+ AgentAction2["WRITE_FILE"] = "WRITE_FILE";
926
+ AgentAction2["EDIT_FILE"] = "EDIT_FILE";
927
+ AgentAction2["DELETE_FILE"] = "DELETE_FILE";
928
+ AgentAction2["RUN_TEST"] = "RUN_TEST";
929
+ AgentAction2["RUN_BUILD"] = "RUN_BUILD";
930
+ AgentAction2["RUN_LINT"] = "RUN_LINT";
931
+ AgentAction2["RUN_SHELL"] = "RUN_SHELL";
932
+ AgentAction2["COMMIT"] = "COMMIT";
933
+ AgentAction2["REVERT"] = "REVERT";
934
+ AgentAction2["BRANCH"] = "BRANCH";
935
+ AgentAction2["MERGE"] = "MERGE";
936
+ AgentAction2["HTTP_GET"] = "HTTP_GET";
937
+ AgentAction2["HTTP_POST"] = "HTTP_POST";
938
+ AgentAction2["MCP_CALL"] = "MCP_CALL";
939
+ AgentAction2["PLAN"] = "PLAN";
940
+ AgentAction2["REVIEW"] = "REVIEW";
941
+ AgentAction2["DECIDE"] = "DECIDE";
942
+ AgentAction2["ASK_USER"] = "ASK_USER";
943
+ AgentAction2["VERIFY_GATE"] = "VERIFY_GATE";
944
+ AgentAction2["SCORE_R"] = "SCORE_R";
945
+ AgentAction2["SEARCH_EXTERNAL"] = "SEARCH_EXTERNAL";
946
+ AgentAction2["FETCH_DOCS"] = "FETCH_DOCS";
947
+ AgentAction2["CITE"] = "CITE";
948
+ AgentAction2["GATE_OPEN"] = "GATE_OPEN";
949
+ AgentAction2["GATE_CLOSE"] = "GATE_CLOSE";
950
+ AgentAction2["DISPATCH"] = "DISPATCH";
951
+ AgentAction2["AUDIT_PHASE"] = "AUDIT_PHASE";
952
+ AgentAction2["SPEC_WRITE"] = "SPEC_WRITE";
953
+ AgentAction2["PHASE_START"] = "PHASE_START";
954
+ AgentAction2["PHASE_END"] = "PHASE_END";
955
+ })(AgentAction || (AgentAction = {}));
956
+ var LLMProvider;
957
+ (function(LLMProvider2) {
958
+ LLMProvider2["ANTHROPIC"] = "anthropic";
959
+ LLMProvider2["OPENAI"] = "openai";
960
+ LLMProvider2["GEMINI"] = "gemini";
961
+ LLMProvider2["OLLAMA"] = "ollama";
962
+ LLMProvider2["MISTRAL"] = "mistral";
963
+ LLMProvider2["COHERE"] = "cohere";
964
+ LLMProvider2["UNKNOWN"] = "unknown";
965
+ })(LLMProvider || (LLMProvider = {}));
966
+ var AgentRole;
967
+ (function(AgentRole2) {
968
+ AgentRole2["SPEC_WRITER"] = "spec-writer";
969
+ AgentRole2["AUDITOR"] = "auditor";
970
+ AgentRole2["IMPLEMENTER"] = "implementer";
971
+ AgentRole2["ADVERSARIAL_REVIEWER"] = "adversarial-reviewer";
972
+ AgentRole2["CONDUCTOR"] = "conductor";
973
+ AgentRole2["DRIFT_DETECTOR"] = "drift-detector";
974
+ AgentRole2["GATEKEEPER"] = "gatekeeper";
975
+ AgentRole2["INTEGRATOR"] = "integrator";
976
+ AgentRole2["RESEARCHER"] = "researcher";
977
+ AgentRole2["DEVSECOPS"] = "devsecops";
978
+ AgentRole2["TECHNICAL_WRITER"] = "technical-writer";
979
+ AgentRole2["RELEASE_MANAGER"] = "release-manager";
980
+ AgentRole2["MASTER_COORDINATOR"] = "master-coordinator";
981
+ })(AgentRole || (AgentRole = {}));
982
+ var METADATA_KEY_RE = /^[a-zA-Z][a-zA-Z0-9]*$/;
983
+ var METADATA_VALUE_MAX = 200;
984
+ function validateMetadata(metadata) {
985
+ for (const [key, value] of Object.entries(metadata)) {
986
+ if (!METADATA_KEY_RE.test(key)) {
987
+ throw new Error(`[observability] Invalid metadata key "${key}": must match /^[a-zA-Z][a-zA-Z0-9]*$/ (camelCase, no hyphens or underscores). Langfuse silently drops non-conforming keys.`);
988
+ }
989
+ if (value.length > METADATA_VALUE_MAX) {
990
+ throw new Error(`[observability] Metadata value for key "${key}" is ${value.length} chars, exceeds ${METADATA_VALUE_MAX} char limit. Langfuse silently drops oversized values.`);
991
+ }
992
+ }
993
+ }
994
+ __name(validateMetadata, "validateMetadata");
995
+ function buildTraceName(role, specId, phaseId, fallback) {
996
+ if (specId && phaseId) return `${role}:${specId}/${phaseId}`;
997
+ return `${role}:${fallback}`;
998
+ }
999
+ __name(buildTraceName, "buildTraceName");
1000
+ var _otelBase = process.env.OTEL_EXPORTER_OTLP_ENDPOINT;
1001
+ var COLLECTOR_ENDPOINT = process.env.COLLECTOR_ENDPOINT ?? process.env.OTLP_ENDPOINT ?? (_otelBase ? `${_otelBase.replace(/\/+$/, "")}/v1/traces` : "http://localhost:4318/v1/traces");
1002
+ var NETWORK_TIMEOUT_MS = 500;
1003
+ function nanoNow() {
1004
+ return String(BigInt(Date.now()) * 1000000n);
1005
+ }
1006
+ __name(nanoNow, "nanoNow");
1007
+ function newSpanId() {
1008
+ return randomUUID().replace(/-/g, "").slice(0, 16);
1009
+ }
1010
+ __name(newSpanId, "newSpanId");
1011
+ function buildAuthHeader() {
1012
+ const pk = process.env.LANGFUSE_PUBLIC_KEY;
1013
+ const sk = process.env.LANGFUSE_SECRET_KEY;
1014
+ if (pk && sk) {
1015
+ return `Basic ${Buffer.from(`${pk}:${sk}`).toString("base64")}`;
1016
+ }
1017
+ return null;
1018
+ }
1019
+ __name(buildAuthHeader, "buildAuthHeader");
1020
+ function toAttr(key, value) {
1021
+ if (typeof value === "boolean") return {
1022
+ key,
1023
+ value: {
1024
+ boolValue: value
1025
+ }
1026
+ };
1027
+ if (typeof value === "number") return {
1028
+ key,
1029
+ value: {
1030
+ intValue: String(value)
1031
+ }
1032
+ };
1033
+ return {
1034
+ key,
1035
+ value: {
1036
+ stringValue: String(value)
1037
+ }
1038
+ };
1039
+ }
1040
+ __name(toAttr, "toAttr");
1041
+ async function emitSpanToCollector(traceId, spanId, parentSpanId, name, attributes, startNano, endNano) {
1042
+ const auth = buildAuthHeader();
1043
+ if (!auth) return;
1044
+ const attrs = Object.entries(attributes).map(([k, v]) => toAttr(k, v));
1045
+ const span = {
1046
+ traceId,
1047
+ spanId,
1048
+ name,
1049
+ kind: 1,
1050
+ startTimeUnixNano: startNano,
1051
+ endTimeUnixNano: endNano ?? nanoNow(),
1052
+ attributes: attrs,
1053
+ status: {
1054
+ code: 0
1055
+ }
1056
+ };
1057
+ if (parentSpanId) span.parentSpanId = parentSpanId;
1058
+ const payload = {
1059
+ resourceSpans: [
1060
+ {
1061
+ resource: {
1062
+ attributes: [
1063
+ toAttr("gen_ai.workflow.name", "vreko-swarm"),
1064
+ toAttr("service.name", "vreko-observability")
1065
+ ]
1066
+ },
1067
+ scopeSpans: [
1068
+ {
1069
+ scope: {
1070
+ name: "vreko.swarm.observability",
1071
+ version: "1.0.0"
1072
+ },
1073
+ spans: [
1074
+ span
1075
+ ]
1076
+ }
1077
+ ]
1078
+ }
1079
+ ]
1080
+ };
1081
+ const controller = new AbortController();
1082
+ const timer = setTimeout(() => controller.abort(), NETWORK_TIMEOUT_MS);
1083
+ try {
1084
+ await fetch(COLLECTOR_ENDPOINT, {
1085
+ method: "POST",
1086
+ headers: {
1087
+ "Content-Type": "application/json",
1088
+ Authorization: auth,
1089
+ "x-langfuse-ingestion-version": "4"
1090
+ },
1091
+ body: JSON.stringify(payload),
1092
+ signal: controller.signal
1093
+ });
1094
+ } catch {
1095
+ } finally {
1096
+ clearTimeout(timer);
1097
+ }
1098
+ }
1099
+ __name(emitSpanToCollector, "emitSpanToCollector");
1100
+ async function recordAction(action, payload, options) {
1101
+ if (options.metadata) {
1102
+ validateMetadata(options.metadata);
1103
+ }
1104
+ const spanId = newSpanId();
1105
+ const startNano = nanoNow();
1106
+ const traceName = buildTraceName(options.agentRole, options.specId, options.phaseId, action);
1107
+ const resolvedModel = options.model ?? process.env.VREKO_AGENT_MODEL;
1108
+ const attributes = {
1109
+ "gen_ai.operation.name": "execute_tool",
1110
+ "vreko.agent.role": options.agentRole,
1111
+ "vreko.action": action,
1112
+ "vreko.trace.name": traceName,
1113
+ "gen_ai.conversation.id": options.traceId
1114
+ };
1115
+ if (resolvedModel) {
1116
+ attributes["gen_ai.request.model"] = resolvedModel;
1117
+ }
1118
+ if (options.userId) attributes["user.id"] = options.userId;
1119
+ if (options.workspaceId) attributes["vreko.workspace.id"] = options.workspaceId;
1120
+ attributes["deployment.environment"] = options.environment ?? process.env.LANGFUSE_TRACING_ENVIRONMENT ?? "unknown";
1121
+ if (options.promptVersion) attributes["vreko.prompt.version"] = options.promptVersion;
1122
+ for (const [k, v] of Object.entries(payload)) {
1123
+ if (typeof v === "string" || typeof v === "number" || typeof v === "boolean") {
1124
+ attributes[`vreko.action.${k}`] = v;
1125
+ }
1126
+ }
1127
+ if (options.metadata) {
1128
+ for (const [k, v] of Object.entries(options.metadata)) {
1129
+ attributes[`vreko.meta.${k}`] = v;
1130
+ }
1131
+ }
1132
+ if (options.transport === "sdk") {
1133
+ return {
1134
+ spanId,
1135
+ traceId: options.traceId,
1136
+ end: /* @__PURE__ */ __name(() => {
1137
+ }, "end")
1138
+ };
1139
+ }
1140
+ await emitSpanToCollector(options.traceId, spanId, options.parentSpanId, traceName, attributes, startNano);
1141
+ nanoNow();
1142
+ return {
1143
+ spanId,
1144
+ traceId: options.traceId,
1145
+ end: /* @__PURE__ */ __name(() => {
1146
+ }, "end")
1147
+ };
1148
+ }
1149
+ __name(recordAction, "recordAction");
1150
+ function validateDecision(decision) {
1151
+ for (const a of decision.invoked) {
1152
+ if (!decision.available.includes(a)) {
1153
+ throw new Error(`[observability] recordDecision: invoked action "${a}" is not in available set at "${decision.decisionPoint}".`);
1154
+ }
1155
+ }
1156
+ const invokedSet = new Set(decision.invoked);
1157
+ const expectedSkipped = decision.available.filter((a) => !invokedSet.has(a));
1158
+ const exp = [
1159
+ ...expectedSkipped
1160
+ ].sort().join(",");
1161
+ const act = [
1162
+ ...decision.skipped
1163
+ ].sort().join(",");
1164
+ if (exp !== act) {
1165
+ throw new Error(`[observability] recordDecision set math invalid at "${decision.decisionPoint}": expected skipped=[${exp}] (available\\invoked) but got skipped=[${act}]. Agent must not misreport available actions.`);
1166
+ }
1167
+ if (decision.rationale.length > 1e3) {
1168
+ throw new Error(`[observability] recordDecision rationale at "${decision.decisionPoint}" exceeds 1000 char limit.`);
1169
+ }
1170
+ }
1171
+ __name(validateDecision, "validateDecision");
1172
+ function buildDecisionAttributes(decision, options) {
1173
+ const hasSkipped = decision.skipped.length > 0;
1174
+ const attrs = {
1175
+ "gen_ai.operation.name": "tool_decision",
1176
+ "vreko.agent.role": options.agentRole,
1177
+ "vreko.decision.point": decision.decisionPoint,
1178
+ "vreko.decision.available": decision.available.join(","),
1179
+ "vreko.decision.invoked": decision.invoked.join(","),
1180
+ "vreko.decision.skipped": decision.skipped.join(","),
1181
+ "vreko.decision.rationale": decision.rationale.slice(0, 1e3),
1182
+ "vreko.decision.hasSkipped": hasSkipped,
1183
+ "gen_ai.conversation.id": options.traceId
1184
+ };
1185
+ if (hasSkipped) attrs["vreko.tag"] = "decision:has-skipped";
1186
+ if (options.metadata) {
1187
+ for (const [k, v] of Object.entries(options.metadata)) attrs[`vreko.meta.${k}`] = v;
1188
+ }
1189
+ return attrs;
1190
+ }
1191
+ __name(buildDecisionAttributes, "buildDecisionAttributes");
1192
+ async function recordDecision(decision, options) {
1193
+ validateDecision(decision);
1194
+ if (options.metadata) validateMetadata(options.metadata);
1195
+ if (options.transport === "sdk") return {
1196
+ spanId: newSpanId(),
1197
+ traceId: options.traceId,
1198
+ end: /* @__PURE__ */ __name(() => {
1199
+ }, "end")
1200
+ };
1201
+ const spanId = newSpanId();
1202
+ const traceName = buildTraceName(options.agentRole, options.specId, options.phaseId, "tool_decision");
1203
+ const attributes = buildDecisionAttributes(decision, options);
1204
+ attributes["vreko.trace.name"] = traceName;
1205
+ await emitSpanToCollector(options.traceId, spanId, options.parentSpanId, traceName, attributes, nanoNow());
1206
+ return {
1207
+ spanId,
1208
+ traceId: options.traceId,
1209
+ end: /* @__PURE__ */ __name(() => {
1210
+ }, "end")
1211
+ };
1212
+ }
1213
+ __name(recordDecision, "recordDecision");
1214
+ async function recordGate(rId, passed, output, traceId, options) {
1215
+ const spanId = newSpanId();
1216
+ const startNano = nanoNow();
1217
+ const roleOrGate = options?.agentRole ?? "gate";
1218
+ const traceName = buildTraceName(roleOrGate, options?.specId, options?.phaseId, `verify_gate:${rId}`);
1219
+ const attributes = {
1220
+ "gen_ai.operation.name": "verify_gate",
1221
+ "vreko.r.id": rId,
1222
+ "vreko.gate.passed": passed,
1223
+ "vreko.gate.output": output.slice(0, 500),
1224
+ "vreko.gate.tag": passed ? "gate:passed" : "gate:failed",
1225
+ "vreko.gate.lastGate": rId,
1226
+ "vreko.trace.name": traceName,
1227
+ "gen_ai.conversation.id": traceId
1228
+ };
1229
+ if (options?.specId) attributes["vreko.spec.id"] = options.specId;
1230
+ if (options?.phaseId) attributes["vreko.phase.name"] = options.phaseId;
1231
+ if (options?.gateOpenedAt) {
1232
+ attributes["vreko.gate.openedAt"] = options.gateOpenedAt;
1233
+ const waitMs = Date.now() - new Date(options.gateOpenedAt).getTime();
1234
+ if (!Number.isNaN(waitMs) && waitMs >= 0) {
1235
+ attributes["vreko.gate.waitDurationMs"] = waitMs;
1236
+ }
1237
+ }
1238
+ if (options?.transport === "sdk") return;
1239
+ await emitSpanToCollector(traceId, spanId, void 0, traceName, attributes, startNano);
1240
+ }
1241
+ __name(recordGate, "recordGate");
1242
+ async function emitPhaseEvent(event, phase, options) {
1243
+ if (event === "start") {
1244
+ return recordAction(AgentAction.PHASE_START, {
1245
+ phase,
1246
+ specId: options.specId,
1247
+ pioneerBlocker: options.pioneerBlocker
1248
+ }, {
1249
+ traceId: options.traceId,
1250
+ agentRole: options.agentRole,
1251
+ specId: options.specId,
1252
+ phaseId: phase,
1253
+ model: options.model,
1254
+ userId: options.userId,
1255
+ workspaceId: options.workspaceId,
1256
+ metadata: options.priority ? {
1257
+ priority: options.priority
1258
+ } : void 0
1259
+ });
1260
+ }
1261
+ return recordAction(AgentAction.PHASE_END, {
1262
+ phase,
1263
+ specId: options.specId,
1264
+ outcome: options.outcome ?? "completed",
1265
+ durationMs: options.durationMs
1266
+ }, {
1267
+ traceId: options.traceId,
1268
+ agentRole: options.agentRole,
1269
+ specId: options.specId,
1270
+ phaseId: phase,
1271
+ model: options.model,
1272
+ userId: options.userId,
1273
+ workspaceId: options.workspaceId
1274
+ });
1275
+ }
1276
+ __name(emitPhaseEvent, "emitPhaseEvent");
1277
+ async function emitRatchetScores(ratchets, traceId, specId, options) {
1278
+ const emits = Object.entries(ratchets).map(([name, { before, after }]) => {
1279
+ const improved = after <= before;
1280
+ const output = `before=${before} after=${after} delta=${after - before}`;
1281
+ return recordGate(`ratchet:${name}`, improved, output, traceId, {
1282
+ specId,
1283
+ agentRole: options?.agentRole
1284
+ });
1285
+ });
1286
+ await Promise.all(emits);
1287
+ }
1288
+ __name(emitRatchetScores, "emitRatchetScores");
1289
+
1290
+ // ../../packages/infrastructure/dist/observability/agent-session.js
1291
+ var AgentSession = class {
1292
+ static {
1293
+ __name(this, "AgentSession");
1294
+ }
1295
+ role;
1296
+ provider;
1297
+ model;
1298
+ sessionId;
1299
+ specId;
1300
+ traceId;
1301
+ options;
1302
+ constructor(config, options = {}) {
1303
+ this.role = config.role;
1304
+ this.provider = config.provider;
1305
+ this.model = config.model;
1306
+ this.sessionId = config.sessionId;
1307
+ this.specId = config.specId;
1308
+ this.traceId = config.traceId || this.generateTraceId();
1309
+ this.options = {
1310
+ timeout: options.timeout ?? 3e4,
1311
+ maxRetries: options.maxRetries ?? 3
1312
+ };
1313
+ }
1314
+ /**
1315
+ * Generate a consistent trace ID from session ID and role
1316
+ */
1317
+ generateTraceId() {
1318
+ `${this.sessionId}-${this.role}-${Date.now()}`;
1319
+ return randomUUID().replace(/-/g, "");
1320
+ }
1321
+ /**
1322
+ * Run an LLM inference with telemetry instrumentation
1323
+ *
1324
+ * Records PLAN and DECIDE actions with provider and model attributes.
1325
+ * Routes to the appropriate SDK based on provider.
1326
+ */
1327
+ async run(prompt, options) {
1328
+ await this.recordAction(AgentAction.PLAN, {
1329
+ description: `prompt[${this.hash(prompt).slice(0, 8)}]`,
1330
+ provider: this.provider,
1331
+ model: this.model
1332
+ });
1333
+ try {
1334
+ const result = await this.dispatch(prompt, options);
1335
+ await this.recordAction(AgentAction.DECIDE, {
1336
+ decision: `output[${this.hash(result.content).slice(0, 8)}]`
1337
+ });
1338
+ return result;
1339
+ } catch (error) {
1340
+ await this.recordAction(AgentAction.DECIDE, {
1341
+ decision: "error",
1342
+ rationale: error instanceof Error ? error.message : String(error)
1343
+ });
1344
+ throw error;
1345
+ }
1346
+ }
1347
+ /**
1348
+ * Dispatch to the appropriate LLM SDK based on provider
1349
+ */
1350
+ async dispatch(prompt, options) {
1351
+ switch (this.provider) {
1352
+ case LLMProvider.ANTHROPIC:
1353
+ return this.runAnthropic(prompt, options);
1354
+ case LLMProvider.OPENAI:
1355
+ return this.runOpenAI(prompt, options);
1356
+ case LLMProvider.GEMINI:
1357
+ return this.runGemini(prompt, options);
1358
+ case LLMProvider.OLLAMA:
1359
+ return this.runOllama(prompt, options);
1360
+ default:
1361
+ return this.runAnthropic(prompt, options);
1362
+ }
1363
+ }
1364
+ /**
1365
+ * Anthropic SDK integration
1366
+ * TODO: Implement with @anthropic-ai/sdk
1367
+ */
1368
+ async runAnthropic(prompt, options) {
1369
+ throw new Error("Anthropic SDK integration not yet implemented");
1370
+ }
1371
+ /**
1372
+ * OpenAI SDK integration
1373
+ * TODO: Implement with openai package
1374
+ */
1375
+ async runOpenAI(prompt, options) {
1376
+ throw new Error("OpenAI SDK integration not yet implemented");
1377
+ }
1378
+ /**
1379
+ * Google Gemini SDK integration
1380
+ * TODO: Implement with @google/generative-ai
1381
+ */
1382
+ async runGemini(prompt, options) {
1383
+ throw new Error("Gemini SDK integration not yet implemented");
1384
+ }
1385
+ /**
1386
+ * Ollama (local model) integration
1387
+ * TODO: Implement with ollama package or HTTP API
1388
+ */
1389
+ async runOllama(prompt, options) {
1390
+ throw new Error("Ollama integration not yet implemented");
1391
+ }
1392
+ async recordAction(action, payload, opts) {
1393
+ await recordAction(action, payload, {
1394
+ traceId: this.traceId,
1395
+ agentRole: this.role,
1396
+ specId: this.specId,
1397
+ model: this.model,
1398
+ ...opts
1399
+ });
1400
+ }
1401
+ /**
1402
+ * Hash sensitive content (prompts, outputs) before recording
1403
+ * Uses SHA-256 for cryptographic hashing
1404
+ */
1405
+ hash(content) {
1406
+ return createHash("sha256").update(content).digest("hex");
1407
+ }
1408
+ /**
1409
+ * Get the trace ID for this session
1410
+ */
1411
+ getTraceId() {
1412
+ return this.traceId;
1413
+ }
1414
+ /**
1415
+ * Get the session ID
1416
+ */
1417
+ getSessionId() {
1418
+ return this.sessionId;
1419
+ }
1420
+ /**
1421
+ * Get provider and model for observability
1422
+ */
1423
+ getProviderInfo() {
1424
+ return {
1425
+ provider: this.provider,
1426
+ model: this.model
1427
+ };
1428
+ }
1429
+ };
1430
+ var execFileAsync = promisify(execFile);
1431
+ var NETWORK_TIMEOUT_MS2 = 5e3;
1432
+ async function langfuseGet(path) {
1433
+ const baseUrl = process.env.LANGFUSE_BASE_URL;
1434
+ const pk = process.env.LANGFUSE_PUBLIC_KEY;
1435
+ const sk = process.env.LANGFUSE_SECRET_KEY;
1436
+ if (!baseUrl?.startsWith("http")) {
1437
+ throw new Error(`LANGFUSE_BASE_URL invalid: expected URL, got "${baseUrl?.slice(0, 20)}..."`);
1438
+ }
1439
+ if (!sk?.startsWith("sk-lf-")) {
1440
+ throw new Error(`LANGFUSE_SECRET_KEY invalid: expected key starting with sk-lf-`);
1441
+ }
1442
+ if (!pk?.startsWith("pk-lf-")) {
1443
+ throw new Error(`LANGFUSE_PUBLIC_KEY invalid: expected key starting with pk-lf-`);
1444
+ }
1445
+ const auth = `Basic ${Buffer.from(`${pk}:${sk}`).toString("base64")}`;
1446
+ const controller = new AbortController();
1447
+ const timer = setTimeout(() => controller.abort(), NETWORK_TIMEOUT_MS2);
1448
+ try {
1449
+ const res = await fetch(`${baseUrl}${path}`, {
1450
+ headers: {
1451
+ Authorization: auth
1452
+ },
1453
+ signal: controller.signal
1454
+ });
1455
+ if (!res.ok) {
1456
+ throw new Error(`Langfuse API error: ${res.status} ${res.statusText}`);
1457
+ }
1458
+ return res.json();
1459
+ } finally {
1460
+ clearTimeout(timer);
1461
+ }
1462
+ }
1463
+ __name(langfuseGet, "langfuseGet");
1464
+ async function failedGatesInLastNRuns(n) {
1465
+ const response = await langfuseGet(`/api/public/scores?dataType=BOOLEAN&value=0&limit=${n * 10}`);
1466
+ const map = /* @__PURE__ */ new Map();
1467
+ for (const score of response.data ?? []) {
1468
+ if (!score.name) continue;
1469
+ const existing = map.get(score.name);
1470
+ if (existing) {
1471
+ existing.count++;
1472
+ if (score.createdAt > existing.lastFailedAt) {
1473
+ existing.lastFailedAt = score.createdAt;
1474
+ }
1475
+ } else {
1476
+ map.set(score.name, {
1477
+ count: 1,
1478
+ lastFailedAt: score.createdAt
1479
+ });
1480
+ }
1481
+ }
1482
+ return Array.from(map.entries()).map(([rId, { count, lastFailedAt }]) => ({
1483
+ rId,
1484
+ count,
1485
+ lastFailedAt
1486
+ })).sort((a, b) => b.count - a.count).slice(0, n);
1487
+ }
1488
+ __name(failedGatesInLastNRuns, "failedGatesInLastNRuns");
1489
+ async function gatesFailingFirstAttempt(specId) {
1490
+ const response = await langfuseGet(`/api/public/scores?dataType=BOOLEAN&limit=200`);
1491
+ const getScoreSpecId = /* @__PURE__ */ __name((score) => score.metadata?.["vreko.spec.id"] ?? score.metadata?.specId, "getScoreSpecId");
1492
+ const firstAttemptMap = /* @__PURE__ */ new Map();
1493
+ const sorted = [
1494
+ ...response.data ?? []
1495
+ ].sort((a, b) => a.createdAt.localeCompare(b.createdAt));
1496
+ for (const score of sorted) {
1497
+ if (!score.name) continue;
1498
+ if (getScoreSpecId(score) !== specId) continue;
1499
+ if (!firstAttemptMap.has(score.name)) {
1500
+ firstAttemptMap.set(score.name, score.value === 0);
1501
+ }
1502
+ }
1503
+ return Array.from(firstAttemptMap.entries()).filter(([, failedFirst]) => failedFirst).map(([rId]) => rId);
1504
+ }
1505
+ __name(gatesFailingFirstAttempt, "gatesFailingFirstAttempt");
1506
+ async function decisionsWithSkips(role, since) {
1507
+ const sinceStr = since.toISOString();
1508
+ const response = await langfuseGet(`/api/public/observations?name=tool_decision&fromStartTime=${sinceStr}&limit=200`);
1509
+ const results = [];
1510
+ for (const obs of response.data ?? []) {
1511
+ const input = obs.input;
1512
+ if (!input) continue;
1513
+ const agentRole = String(input["vreko.agent.role"] ?? "");
1514
+ if (agentRole !== role) continue;
1515
+ const skippedStr = String(input["vreko.decision.skipped"] ?? "");
1516
+ if (!skippedStr) continue;
1517
+ results.push({
1518
+ available: String(input["vreko.decision.available"] ?? "").split(",").filter(Boolean),
1519
+ invoked: String(input["vreko.decision.invoked"] ?? "").split(",").filter(Boolean),
1520
+ skipped: skippedStr.split(",").filter(Boolean),
1521
+ rationale: String(input["vreko.decision.rationale"] ?? ""),
1522
+ decisionPoint: String(input["vreko.decision.point"] ?? "")
1523
+ });
1524
+ }
1525
+ return results;
1526
+ }
1527
+ __name(decisionsWithSkips, "decisionsWithSkips");
1528
+ async function lookupTraceByGitSha(sha, commitTime) {
1529
+ const windowMs = 60 * 60 * 1e3;
1530
+ const from = new Date(commitTime.getTime() - windowMs).toISOString();
1531
+ const to = new Date(commitTime.getTime() + windowMs).toISOString();
1532
+ try {
1533
+ const response = await langfuseGet(`/api/public/traces?fromTimestamp=${encodeURIComponent(from)}&toTimestamp=${encodeURIComponent(to)}&limit=100`);
1534
+ return response.data?.find((t) => t.metadata?.["vreko.git.sha.end"] === sha);
1535
+ } catch {
1536
+ return void 0;
1537
+ }
1538
+ }
1539
+ __name(lookupTraceByGitSha, "lookupTraceByGitSha");
1540
+ async function attributionChain(filePath, options) {
1541
+ const limit = options?.limit ?? 50;
1542
+ const gitArgs = [
1543
+ "log",
1544
+ "--follow",
1545
+ "--pretty=format:%H|%ae|%ad|%s",
1546
+ "--date=iso",
1547
+ "-n",
1548
+ String(limit),
1549
+ "--",
1550
+ filePath
1551
+ ];
1552
+ if (options?.since) {
1553
+ gitArgs.splice(gitArgs.indexOf("--"), 0, "--after=" + options.since.toISOString());
1554
+ }
1555
+ let stdout;
1556
+ try {
1557
+ const result = await execFileAsync("git", gitArgs, {
1558
+ encoding: "utf-8"
1559
+ });
1560
+ stdout = result.stdout;
1561
+ } catch {
1562
+ return {
1563
+ filePath,
1564
+ links: [],
1565
+ modelSummary: {},
1566
+ providerSummary: {},
1567
+ humanCommits: 0,
1568
+ coverage: 0
1569
+ };
1570
+ }
1571
+ const lines = stdout.trim().split("\n").filter(Boolean);
1572
+ const links = [];
1573
+ let humanCommits = 0;
1574
+ for (const line of lines) {
1575
+ const pipeIdx1 = line.indexOf("|");
1576
+ const pipeIdx2 = line.indexOf("|", pipeIdx1 + 1);
1577
+ const pipeIdx3 = line.indexOf("|", pipeIdx2 + 1);
1578
+ if (pipeIdx1 === -1 || pipeIdx2 === -1 || pipeIdx3 === -1) continue;
1579
+ const sha = line.slice(0, pipeIdx1).trim();
1580
+ const email = line.slice(pipeIdx1 + 1, pipeIdx2).trim();
1581
+ const dateStr = line.slice(pipeIdx2 + 1, pipeIdx3).trim();
1582
+ const subject = line.slice(pipeIdx3 + 1).trim();
1583
+ if (!sha || !email) continue;
1584
+ const committedAt = new Date(dateStr);
1585
+ if (Number.isNaN(committedAt.getTime())) continue;
1586
+ const isConventionalCommit = /^(fix|feat|chore|refactor|test|docs|style|perf)\(/.test(subject);
1587
+ if (!isConventionalCommit) {
1588
+ humanCommits++;
1589
+ if (options?.includeHuman === false) continue;
1590
+ }
1591
+ const trace2 = await lookupTraceByGitSha(sha, committedAt);
1592
+ const traceMetadata = trace2?.metadata ?? {};
1593
+ const authorModel = typeof traceMetadata["gen_ai.request.model"] === "string" ? traceMetadata["gen_ai.request.model"] : "unknown";
1594
+ const rawProvider = typeof traceMetadata["gen_ai.provider.name"] === "string" ? traceMetadata["gen_ai.provider.name"] : void 0;
1595
+ const authorProvider = Object.values(LLMProvider).includes(rawProvider ?? "") ? rawProvider : LLMProvider.UNKNOWN;
1596
+ const rawRole = typeof traceMetadata["gen_ai.agent.role"] === "string" ? traceMetadata["gen_ai.agent.role"] : void 0;
1597
+ const agentRole = Object.values(AgentRole).includes(rawRole ?? "") ? rawRole : AgentRole.IMPLEMENTER;
1598
+ const specId = typeof traceMetadata["vreko.spec.id"] === "string" ? traceMetadata["vreko.spec.id"] : void 0;
1599
+ links.push({
1600
+ commitSha: sha,
1601
+ committedAt,
1602
+ authorModel,
1603
+ authorProvider,
1604
+ agentRole,
1605
+ traceId: trace2?.id ?? "",
1606
+ specId,
1607
+ linesAdded: void 0,
1608
+ linesRemoved: void 0
1609
+ });
1610
+ }
1611
+ const totalCommits = lines.length;
1612
+ const tracedLinks = links.filter((l) => l.traceId);
1613
+ const coverage = totalCommits > 0 ? tracedLinks.length / totalCommits : 0;
1614
+ const modelSummary = {};
1615
+ const providerSummary = {};
1616
+ for (const link of tracedLinks) {
1617
+ modelSummary[link.authorModel] = (modelSummary[link.authorModel] ?? 0) + 1;
1618
+ providerSummary[link.authorProvider] = (providerSummary[link.authorProvider] ?? 0) + 1;
1619
+ }
1620
+ return {
1621
+ filePath,
1622
+ links,
1623
+ modelSummary,
1624
+ providerSummary,
1625
+ humanCommits,
1626
+ coverage
1627
+ };
1628
+ }
1629
+ __name(attributionChain, "attributionChain");
1630
+ async function gitCommitsWithoutProvenance(filePath, limit = 50) {
1631
+ const chain = await attributionChain(filePath, {
1632
+ limit
1633
+ });
1634
+ return chain.links.filter((l) => !l.traceId).map((l) => l.commitSha);
1635
+ }
1636
+ __name(gitCommitsWithoutProvenance, "gitCommitsWithoutProvenance");
1637
+ async function conductorSessionInsights(n = 20) {
1638
+ const staleSinceTimestamp = (/* @__PURE__ */ new Date()).toISOString();
1639
+ let rawGateFailures = [];
1640
+ try {
1641
+ rawGateFailures = await failedGatesInLastNRuns(n);
1642
+ } catch {
1643
+ }
1644
+ const gateFailureRatesByAgent = rawGateFailures.map((g) => ({
1645
+ agent: g.rId,
1646
+ firstAttemptFailRate: 1,
1647
+ sampleSize: g.count
1648
+ }));
1649
+ const toolSkipRatesByRole = [];
1650
+ const since = new Date(Date.now() - n * 24 * 60 * 60 * 1e3);
1651
+ for (const role of Object.values(AgentRole)) {
1652
+ let decisions = [];
1653
+ try {
1654
+ decisions = await decisionsWithSkips(role, since);
1655
+ } catch {
1656
+ continue;
1657
+ }
1658
+ if (decisions.length === 0) continue;
1659
+ const skipCount = decisions.reduce((sum, d) => sum + d.skipped.length, 0);
1660
+ toolSkipRatesByRole.push({
1661
+ role,
1662
+ skipCount,
1663
+ totalDecisions: decisions.length
1664
+ });
1665
+ }
1666
+ const costByAgentLastNRuns = [];
1667
+ return {
1668
+ gateFailureRatesByAgent,
1669
+ costByAgentLastNRuns,
1670
+ toolSkipRatesByRole,
1671
+ staleSinceTimestamp
1672
+ };
1673
+ }
1674
+ __name(conductorSessionInsights, "conductorSessionInsights");
1675
+ async function createAlert(config) {
1676
+ try {
1677
+ logger.info({
1678
+ alert: config
1679
+ }, "PostHog Alert Configuration (Manual Setup Required)");
1680
+ return `alert_${Date.now()}_${Math.random().toString(36).substring(2, 11)}`;
1681
+ } catch (error) {
1682
+ logger.error({
1683
+ error,
1684
+ config
1685
+ }, "Failed to create PostHog alert");
1686
+ throw new Error("Failed to create PostHog alert");
1687
+ }
1688
+ }
1689
+ __name(createAlert, "createAlert");
1690
+ async function getAlerts() {
1691
+ try {
1692
+ return [];
1693
+ } catch (error) {
1694
+ logger.error({
1695
+ error
1696
+ }, "Failed to fetch PostHog alerts");
1697
+ throw new Error("Failed to fetch PostHog alerts");
1698
+ }
1699
+ }
1700
+ __name(getAlerts, "getAlerts");
1701
+ async function toggleAlert(alertId, enabled) {
1702
+ try {
1703
+ logger.info({
1704
+ alertId,
1705
+ enabled
1706
+ }, "Toggling PostHog alert");
1707
+ return true;
1708
+ } catch (error) {
1709
+ logger.error({
1710
+ error,
1711
+ alertId,
1712
+ enabled
1713
+ }, "Failed to toggle PostHog alert");
1714
+ throw new Error("Failed to toggle PostHog alert");
1715
+ }
1716
+ }
1717
+ __name(toggleAlert, "toggleAlert");
1718
+ async function deleteAlert(alertId) {
1719
+ try {
1720
+ logger.info({
1721
+ alertId
1722
+ }, "Deleting PostHog alert");
1723
+ return true;
1724
+ } catch (error) {
1725
+ logger.error({
1726
+ error,
1727
+ alertId
1728
+ }, "Failed to delete PostHog alert");
1729
+ throw new Error("Failed to delete PostHog alert");
1730
+ }
1731
+ }
1732
+ __name(deleteAlert, "deleteAlert");
1733
+ async function registerKeyMetricAlerts() {
1734
+ const posthogKey = process.env.POSTHOG_PERSONAL_API_KEY;
1735
+ const environmentId = process.env.POSTHOG_ENVIRONMENT_ID;
1736
+ if (!posthogKey) {
1737
+ logger.warn("POSTHOG_PERSONAL_API_KEY not set - skipping PostHog alerts registration");
1738
+ return;
1739
+ }
1740
+ if (!environmentId) {
1741
+ logger.warn("POSTHOG_ENVIRONMENT_ID not set - skipping PostHog alerts registration");
1742
+ return;
1743
+ }
1744
+ try {
1745
+ logger.info({
1746
+ count: KEY_METRIC_ALERTS.length
1747
+ }, "Registering PostHog key metric alerts");
1748
+ for (const alertConfig of KEY_METRIC_ALERTS) {
1749
+ await createAlert(alertConfig);
1750
+ }
1751
+ logger.info("Successfully registered all PostHog key metric alerts");
1752
+ } catch (error) {
1753
+ logger.error({
1754
+ error
1755
+ }, "Failed to register PostHog alerts");
1756
+ }
1757
+ }
1758
+ __name(registerKeyMetricAlerts, "registerKeyMetricAlerts");
1759
+ var KEY_METRIC_ALERTS = [
1760
+ {
1761
+ name: "TTFV p75 Alert",
1762
+ insightId: "ttfv_insight",
1763
+ series: "ttfv_p75",
1764
+ type: "value",
1765
+ threshold: 7,
1766
+ thresholdType: "absolute",
1767
+ frequency: "daily",
1768
+ recipients: [
1769
+ "engineering-team@vreko.ai"
1770
+ ]
1771
+ },
1772
+ {
1773
+ name: "Onboarding Completion Rate Alert",
1774
+ insightId: "onboarding_insight",
1775
+ series: "completion_rate",
1776
+ type: "value",
1777
+ threshold: 60,
1778
+ thresholdType: "absolute",
1779
+ frequency: "daily",
1780
+ recipients: [
1781
+ "product-team@vreko.ai"
1782
+ ]
1783
+ },
1784
+ {
1785
+ name: "Crash-free Sessions Alert",
1786
+ insightId: "crash_insight",
1787
+ series: "crash_free_rate",
1788
+ type: "value",
1789
+ threshold: 95,
1790
+ thresholdType: "absolute",
1791
+ frequency: "daily",
1792
+ recipients: [
1793
+ "engineering-team@vreko.ai"
1794
+ ]
1795
+ },
1796
+ {
1797
+ name: "Replay Budget Alert",
1798
+ insightId: "replay_insight",
1799
+ series: "replay_budget",
1800
+ type: "value",
1801
+ threshold: 80,
1802
+ thresholdType: "percentage",
1803
+ frequency: "weekly",
1804
+ recipients: [
1805
+ "analytics-team@vreko.ai"
1806
+ ]
1807
+ },
1808
+ {
1809
+ name: "D7 Retention Alert",
1810
+ insightId: "retention_insight",
1811
+ series: "d7_retention",
1812
+ type: "decrease",
1813
+ threshold: 5,
1814
+ thresholdType: "percentage",
1815
+ frequency: "weekly",
1816
+ recipients: [
1817
+ "growth-team@vreko.ai"
1818
+ ]
1819
+ }
1820
+ ];
1821
+ var posthogClient = null;
1822
+ var posthogApiKey = null;
1823
+ var posthogHost = null;
1824
+ function getPostHog() {
1825
+ if (!posthogClient) {
1826
+ const posthogKey = process.env.POSTHOG_PERSONAL_API_KEY;
1827
+ if (!posthogKey) {
1828
+ throw new Error("PostHog personal API key not configured");
1829
+ }
1830
+ const host = process.env.POSTHOG_HOST || "https://app.posthog.com";
1831
+ posthogClient = new PostHog(posthogKey, {
1832
+ host
1833
+ });
1834
+ posthogApiKey = posthogKey;
1835
+ posthogHost = host;
1836
+ }
1837
+ return posthogClient;
1838
+ }
1839
+ __name(getPostHog, "getPostHog");
1840
+ function getPostHogConfig() {
1841
+ if (!posthogApiKey || !posthogHost) {
1842
+ getPostHog();
1843
+ }
1844
+ if (!posthogApiKey || !posthogHost) {
1845
+ throw new Error("PostHog configuration not initialized");
1846
+ }
1847
+ return {
1848
+ apiKey: posthogApiKey,
1849
+ host: posthogHost
1850
+ };
1851
+ }
1852
+ __name(getPostHogConfig, "getPostHogConfig");
1853
+ async function createCohort(config) {
1854
+ try {
1855
+ getPostHog();
1856
+ const phConfig = getPostHogConfig();
1857
+ const response = await fetch(`${phConfig.host}/api/projects/@current/cohorts/`, {
1858
+ method: "POST",
1859
+ headers: {
1860
+ Authorization: `Bearer ${phConfig.apiKey}`,
1861
+ "Content-Type": "application/json"
1862
+ },
1863
+ body: JSON.stringify({
1864
+ name: config.name,
1865
+ description: config.description,
1866
+ filters: config.filters,
1867
+ is_static: config.is_static
1868
+ })
1869
+ });
1870
+ if (!response.ok) {
1871
+ throw new Error(`Failed to create cohort: ${response.statusText}`);
1872
+ }
1873
+ const cohort = await response.json();
1874
+ logger.info({
1875
+ cohort
1876
+ }, "Created PostHog cohort");
1877
+ return cohort;
1878
+ } catch (error) {
1879
+ logger.error({
1880
+ error,
1881
+ config
1882
+ }, "Failed to create PostHog cohort");
1883
+ throw new Error(`Failed to create PostHog cohort: ${error instanceof Error ? error.message : "Unknown error"}`);
1884
+ }
1885
+ }
1886
+ __name(createCohort, "createCohort");
1887
+ async function getCohorts() {
1888
+ try {
1889
+ getPostHog();
1890
+ const phConfig = getPostHogConfig();
1891
+ const response = await fetch(`${phConfig.host}/api/projects/@current/cohorts/`, {
1892
+ method: "GET",
1893
+ headers: {
1894
+ Authorization: `Bearer ${phConfig.apiKey}`,
1895
+ "Content-Type": "application/json"
1896
+ }
1897
+ });
1898
+ if (!response.ok) {
1899
+ throw new Error(`Failed to fetch cohorts: ${response.statusText}`);
1900
+ }
1901
+ const data = await response.json();
1902
+ return data.results || [];
1903
+ } catch (error) {
1904
+ logger.error({
1905
+ error
1906
+ }, "Failed to fetch PostHog cohorts");
1907
+ throw new Error(`Failed to fetch PostHog cohorts: ${error instanceof Error ? error.message : "Unknown error"}`);
1908
+ }
1909
+ }
1910
+ __name(getCohorts, "getCohorts");
1911
+ async function getCohort(cohortId) {
1912
+ try {
1913
+ getPostHog();
1914
+ const phConfig = getPostHogConfig();
1915
+ const response = await fetch(`${phConfig.host}/api/projects/@current/cohorts/${cohortId}/`, {
1916
+ method: "GET",
1917
+ headers: {
1918
+ Authorization: `Bearer ${phConfig.apiKey}`,
1919
+ "Content-Type": "application/json"
1920
+ }
1921
+ });
1922
+ if (!response.ok) {
1923
+ throw new Error(`Failed to fetch cohort: ${response.statusText}`);
1924
+ }
1925
+ const cohort = await response.json();
1926
+ return cohort;
1927
+ } catch (error) {
1928
+ logger.error({
1929
+ error,
1930
+ cohortId
1931
+ }, "Failed to fetch PostHog cohort");
1932
+ throw new Error(`Failed to fetch PostHog cohort: ${error instanceof Error ? error.message : "Unknown error"}`);
1933
+ }
1934
+ }
1935
+ __name(getCohort, "getCohort");
1936
+ async function updateCohort(cohortId, config) {
1937
+ try {
1938
+ getPostHog();
1939
+ const phConfig = getPostHogConfig();
1940
+ const response = await fetch(`${phConfig.host}/api/projects/@current/cohorts/${cohortId}/`, {
1941
+ method: "PATCH",
1942
+ headers: {
1943
+ Authorization: `Bearer ${phConfig.apiKey}`,
1944
+ "Content-Type": "application/json"
1945
+ },
1946
+ body: JSON.stringify(config)
1947
+ });
1948
+ if (!response.ok) {
1949
+ throw new Error(`Failed to update cohort: ${response.statusText}`);
1950
+ }
1951
+ const cohort = await response.json();
1952
+ logger.info({
1953
+ cohort
1954
+ }, "Updated PostHog cohort");
1955
+ return cohort;
1956
+ } catch (error) {
1957
+ logger.error({
1958
+ error,
1959
+ cohortId,
1960
+ config
1961
+ }, "Failed to update PostHog cohort");
1962
+ throw new Error(`Failed to update PostHog cohort: ${error instanceof Error ? error.message : "Unknown error"}`);
1963
+ }
1964
+ }
1965
+ __name(updateCohort, "updateCohort");
1966
+ async function deleteCohort(cohortId) {
1967
+ try {
1968
+ getPostHog();
1969
+ const phConfig = getPostHogConfig();
1970
+ const response = await fetch(`${phConfig.host}/api/projects/@current/cohorts/${cohortId}/`, {
1971
+ method: "DELETE",
1972
+ headers: {
1973
+ Authorization: `Bearer ${phConfig.apiKey}`,
1974
+ "Content-Type": "application/json"
1975
+ }
1976
+ });
1977
+ if (!response.ok) {
1978
+ throw new Error(`Failed to delete cohort: ${response.statusText}`);
1979
+ }
1980
+ logger.info({
1981
+ cohortId
1982
+ }, "Deleted PostHog cohort");
1983
+ } catch (error) {
1984
+ logger.error({
1985
+ error,
1986
+ cohortId
1987
+ }, "Failed to delete PostHog cohort");
1988
+ throw new Error(`Failed to delete PostHog cohort: ${error instanceof Error ? error.message : "Unknown error"}`);
1989
+ }
1990
+ }
1991
+ __name(deleteCohort, "deleteCohort");
1992
+ async function getCohortMembers(cohortId) {
1993
+ try {
1994
+ getPostHog();
1995
+ const phConfig = getPostHogConfig();
1996
+ const response = await fetch(`${phConfig.host}/api/projects/@current/cohorts/${cohortId}/persons/`, {
1997
+ method: "GET",
1998
+ headers: {
1999
+ Authorization: `Bearer ${phConfig.apiKey}`,
2000
+ "Content-Type": "application/json"
2001
+ }
2002
+ });
2003
+ if (!response.ok) {
2004
+ throw new Error(`Failed to fetch cohort members: ${response.statusText}`);
2005
+ }
2006
+ const data = await response.json();
2007
+ return data.results || [];
2008
+ } catch (error) {
2009
+ logger.error({
2010
+ error,
2011
+ cohortId
2012
+ }, "Failed to fetch PostHog cohort members");
2013
+ throw new Error(`Failed to fetch PostHog cohort members: ${error instanceof Error ? error.message : "Unknown error"}`);
2014
+ }
2015
+ }
2016
+ __name(getCohortMembers, "getCohortMembers");
2017
+ var RETENTION_COHORTS = [
2018
+ {
2019
+ name: "D7 Retention",
2020
+ description: "Users who return within 7 days of their first activity",
2021
+ filters: {
2022
+ properties: [
2023
+ {
2024
+ key: "first_seen",
2025
+ value: "7 days",
2026
+ operator: "within",
2027
+ type: "event"
2028
+ }
2029
+ ]
2030
+ }
2031
+ },
2032
+ {
2033
+ name: "D30 Retention",
2034
+ description: "Users who return within 30 days of their first activity",
2035
+ filters: {
2036
+ properties: [
2037
+ {
2038
+ key: "first_seen",
2039
+ value: "30 days",
2040
+ operator: "within",
2041
+ type: "event"
2042
+ }
2043
+ ]
2044
+ }
2045
+ },
2046
+ {
2047
+ name: "Onboarding Completion Cohort",
2048
+ description: "Users who completed the onboarding process",
2049
+ filters: {
2050
+ properties: [
2051
+ {
2052
+ key: "onboarding_completed",
2053
+ value: true,
2054
+ operator: "exact",
2055
+ type: "event"
2056
+ }
2057
+ ]
2058
+ }
2059
+ },
2060
+ {
2061
+ name: "High Engagement Users",
2062
+ description: "Users with high engagement (5+ sessions in 7 days)",
2063
+ filters: {
2064
+ properties: [
2065
+ {
2066
+ key: "session_count",
2067
+ value: 5,
2068
+ operator: "gt",
2069
+ type: "event"
2070
+ },
2071
+ {
2072
+ key: "activity_period",
2073
+ value: "7 days",
2074
+ operator: "within",
2075
+ type: "event"
2076
+ }
2077
+ ]
2078
+ }
2079
+ }
2080
+ ];
2081
+ var CORRELATION_COHORTS = [
2082
+ {
2083
+ name: "Feature Power Users",
2084
+ description: "Users who use advanced features regularly",
2085
+ filters: {
2086
+ properties: [
2087
+ {
2088
+ key: "advanced_feature_usage",
2089
+ value: true,
2090
+ operator: "exact",
2091
+ type: "event"
2092
+ }
2093
+ ]
2094
+ }
2095
+ },
2096
+ {
2097
+ name: "At-Risk Churn",
2098
+ description: "Users showing signs of disengagement",
2099
+ filters: {
2100
+ properties: [
2101
+ {
2102
+ key: "days_since_last_activity",
2103
+ value: 14,
2104
+ operator: "gt",
2105
+ type: "event"
2106
+ }
2107
+ ]
2108
+ }
2109
+ },
2110
+ {
2111
+ name: "Free to Paid Converters",
2112
+ description: "Users who upgraded from free to paid plan",
2113
+ filters: {
2114
+ properties: [
2115
+ {
2116
+ key: "plan_upgrade",
2117
+ value: "free_to_paid",
2118
+ operator: "exact",
2119
+ type: "event"
2120
+ }
2121
+ ]
2122
+ }
2123
+ }
2124
+ ];
2125
+ var posthogClient2 = null;
2126
+ function getPostHog2() {
2127
+ if (!posthogClient2) {
2128
+ const posthogKey = process.env.POSTHOG_PERSONAL_API_KEY;
2129
+ if (!posthogKey) {
2130
+ throw new Error("PostHog personal API key not configured");
2131
+ }
2132
+ const posthogHost2 = process.env.POSTHOG_HOST || "https://app.posthog.com";
2133
+ posthogClient2 = new PostHog(posthogKey, {
2134
+ host: posthogHost2
2135
+ });
2136
+ }
2137
+ return posthogClient2;
2138
+ }
2139
+ __name(getPostHog2, "getPostHog");
2140
+ async function performCorrelationAnalysis(config) {
2141
+ try {
2142
+ const _posthog = getPostHog2();
2143
+ logger.info({
2144
+ config
2145
+ }, "Performing correlation analysis");
2146
+ const results = config.propertyNames.map((property, _index) => ({
2147
+ property,
2148
+ correlation: Math.random() * 2 - 1,
2149
+ count: Math.floor(Math.random() * 1e3) + 100,
2150
+ relativeFrequency: Math.random()
2151
+ }));
2152
+ results.sort((a, b) => Math.abs(b.correlation) - Math.abs(a.correlation));
2153
+ const analysis = {
2154
+ id: `correlation_${Date.now()}`,
2155
+ name: config.name,
2156
+ createdAt: (/* @__PURE__ */ new Date()).toISOString(),
2157
+ results: results.slice(0, 10)
2158
+ };
2159
+ logger.info({
2160
+ analysis
2161
+ }, "Correlation analysis completed");
2162
+ return analysis;
2163
+ } catch (error) {
2164
+ logger.error({
2165
+ error,
2166
+ config
2167
+ }, "Failed to perform correlation analysis");
2168
+ throw new Error(`Failed to perform correlation analysis: ${error instanceof Error ? error.message : "Unknown error"}`);
2169
+ }
2170
+ }
2171
+ __name(performCorrelationAnalysis, "performCorrelationAnalysis");
2172
+ async function getCorrelationAnalysis(analysisId) {
2173
+ try {
2174
+ throw new Error("Correlation analysis persistence not implemented");
2175
+ } catch (error) {
2176
+ logger.error({
2177
+ error,
2178
+ analysisId
2179
+ }, "Failed to fetch correlation analysis");
2180
+ throw new Error(`Failed to fetch correlation analysis: ${error instanceof Error ? error.message : "Unknown error"}`);
2181
+ }
2182
+ }
2183
+ __name(getCorrelationAnalysis, "getCorrelationAnalysis");
2184
+ var CORRELATION_ANALYSES = [
2185
+ {
2186
+ name: "Onboarding Completion Factors",
2187
+ eventName: "onboarding_completed",
2188
+ propertyNames: [
2189
+ "signup_source",
2190
+ "device_type",
2191
+ "browser",
2192
+ "utm_campaign",
2193
+ "time_to_complete",
2194
+ "steps_completed",
2195
+ "help_articles_viewed"
2196
+ ]
2197
+ },
2198
+ {
2199
+ name: "Feature Adoption Correlations",
2200
+ eventName: "feature_used",
2201
+ propertyNames: [
2202
+ "user_plan",
2203
+ "account_age_days",
2204
+ "session_frequency",
2205
+ "support_tickets",
2206
+ "documentation_views",
2207
+ "community_posts"
2208
+ ]
2209
+ },
2210
+ {
2211
+ name: "Churn Risk Indicators",
2212
+ eventName: "account_deactivated",
2213
+ propertyNames: [
2214
+ "days_since_last_activity",
2215
+ "feature_usage_count",
2216
+ "support_ticket_count",
2217
+ "billing_issues",
2218
+ "plan_downgrade",
2219
+ "session_duration_avg"
2220
+ ]
2221
+ },
2222
+ {
2223
+ name: "High Value User Characteristics",
2224
+ eventName: "plan_upgraded",
2225
+ propertyNames: [
2226
+ "initial_plan",
2227
+ "signup_source",
2228
+ "feature_discovery_rate",
2229
+ "engagement_score",
2230
+ "referral_count",
2231
+ "content_creation"
2232
+ ]
2233
+ }
2234
+ ];
2235
+
2236
+ // ../../packages/infrastructure/dist/prometheus/index.js
2237
+ var prometheus_exports = {};
2238
+ __export(prometheus_exports, {
2239
+ client: () => client,
2240
+ dbConnections: () => dbConnections,
2241
+ dbQueryDurationSeconds: () => dbQueryDurationSeconds,
2242
+ getContentType: () => getContentType,
2243
+ getMetrics: () => getMetrics,
2244
+ healthCheckDurationSeconds: () => healthCheckDurationSeconds,
2245
+ healthCheckFailuresTotal: () => healthCheckFailuresTotal,
2246
+ healthCheckLastSuccessTimestamp: () => healthCheckLastSuccessTimestamp,
2247
+ healthCheckStatus: () => healthCheckStatus,
2248
+ httpRequestDurationSeconds: () => httpRequestDurationSeconds,
2249
+ httpRequestsTotal: () => httpRequestsTotal,
2250
+ mcpActiveSessions: () => mcpActiveSessions,
2251
+ mcpProxyErrorsTotal: () => mcpProxyErrorsTotal,
2252
+ readinessProbeLastSuccessTimestamp: () => readinessProbeLastSuccessTimestamp,
2253
+ readinessProbeStatus: () => readinessProbeStatus,
2254
+ recordHealthCheck: () => recordHealthCheck,
2255
+ recordReadinessProbe: () => recordReadinessProbe,
2256
+ recordStartupComplete: () => recordStartupComplete,
2257
+ registry: () => registry,
2258
+ sseConnectionsTotal: () => sseConnectionsTotal,
2259
+ startupProbeDurationSeconds: () => startupProbeDurationSeconds,
2260
+ startupProbeFailuresTotal: () => startupProbeFailuresTotal
2261
+ });
2262
+ var registry = new client.Registry();
2263
+ var defaultMetrics = client.collectDefaultMetrics;
2264
+ defaultMetrics({
2265
+ register: registry
2266
+ });
2267
+ var healthCheckStatus = new client.Gauge({
2268
+ name: "health_check_status",
2269
+ help: "Current health check status (1=healthy, 0=unhealthy)",
2270
+ labelNames: [
2271
+ "service",
2272
+ "check"
2273
+ ],
2274
+ registers: [
2275
+ registry
2276
+ ]
2277
+ });
2278
+ var healthCheckFailuresTotal = new client.Counter({
2279
+ name: "health_check_failures_total",
2280
+ help: "Total number of health check failures",
2281
+ labelNames: [
2282
+ "service",
2283
+ "check",
2284
+ "reason"
2285
+ ],
2286
+ registers: [
2287
+ registry
2288
+ ]
2289
+ });
2290
+ var healthCheckDurationSeconds = new client.Histogram({
2291
+ name: "health_check_duration_seconds",
2292
+ help: "Duration of health check execution in seconds",
2293
+ labelNames: [
2294
+ "service",
2295
+ "check"
2296
+ ],
2297
+ buckets: [
2298
+ 1e-3,
2299
+ 5e-3,
2300
+ 0.01,
2301
+ 0.025,
2302
+ 0.05,
2303
+ 0.1,
2304
+ 0.25,
2305
+ 0.5,
2306
+ 1,
2307
+ 2.5,
2308
+ 5,
2309
+ 10
2310
+ ],
2311
+ registers: [
2312
+ registry
2313
+ ]
2314
+ });
2315
+ var healthCheckLastSuccessTimestamp = new client.Gauge({
2316
+ name: "health_check_last_success_timestamp_seconds",
2317
+ help: "Unix timestamp of the last successful health check",
2318
+ labelNames: [
2319
+ "service",
2320
+ "check"
2321
+ ],
2322
+ registers: [
2323
+ registry
2324
+ ]
2325
+ });
2326
+ var startupProbeFailuresTotal = new client.Counter({
2327
+ name: "startup_probe_failures_total",
2328
+ help: "Total number of startup probe failures",
2329
+ labelNames: [
2330
+ "service"
2331
+ ],
2332
+ registers: [
2333
+ registry
2334
+ ]
2335
+ });
2336
+ var startupProbeDurationSeconds = new client.Gauge({
2337
+ name: "startup_probe_duration_seconds",
2338
+ help: "Time taken for service startup in seconds",
2339
+ labelNames: [
2340
+ "service"
2341
+ ],
2342
+ registers: [
2343
+ registry
2344
+ ]
2345
+ });
2346
+ var readinessProbeStatus = new client.Gauge({
2347
+ name: "readiness_probe_status",
2348
+ help: "Current readiness probe status (1=ready, 0=not_ready)",
2349
+ labelNames: [
2350
+ "service"
2351
+ ],
2352
+ registers: [
2353
+ registry
2354
+ ]
2355
+ });
2356
+ var readinessProbeLastSuccessTimestamp = new client.Gauge({
2357
+ name: "readiness_probe_last_success_timestamp_seconds",
2358
+ help: "Unix timestamp of the last successful readiness probe",
2359
+ labelNames: [
2360
+ "service"
2361
+ ],
2362
+ registers: [
2363
+ registry
2364
+ ]
2365
+ });
2366
+ var httpRequestDurationSeconds = new client.Histogram({
2367
+ name: "http_request_duration_seconds",
2368
+ help: "Duration of HTTP requests in seconds",
2369
+ labelNames: [
2370
+ "method",
2371
+ "path",
2372
+ "status"
2373
+ ],
2374
+ buckets: [
2375
+ 1e-3,
2376
+ 5e-3,
2377
+ 0.01,
2378
+ 0.025,
2379
+ 0.05,
2380
+ 0.1,
2381
+ 0.25,
2382
+ 0.5,
2383
+ 1,
2384
+ 2.5,
2385
+ 5
2386
+ ],
2387
+ registers: [
2388
+ registry
2389
+ ]
2390
+ });
2391
+ var httpRequestsTotal = new client.Counter({
2392
+ name: "http_requests_total",
2393
+ help: "Total number of HTTP requests",
2394
+ labelNames: [
2395
+ "method",
2396
+ "path",
2397
+ "status"
2398
+ ],
2399
+ registers: [
2400
+ registry
2401
+ ]
2402
+ });
2403
+ var dbConnections = new client.Gauge({
2404
+ name: "db_connections",
2405
+ help: "Current number of database connections",
2406
+ labelNames: [
2407
+ "pool",
2408
+ "state"
2409
+ ],
2410
+ registers: [
2411
+ registry
2412
+ ]
2413
+ });
2414
+ var dbQueryDurationSeconds = new client.Histogram({
2415
+ name: "db_query_duration_seconds",
2416
+ help: "Duration of database queries in seconds",
2417
+ labelNames: [
2418
+ "operation",
2419
+ "table"
2420
+ ],
2421
+ buckets: [
2422
+ 1e-3,
2423
+ 5e-3,
2424
+ 0.01,
2425
+ 0.025,
2426
+ 0.05,
2427
+ 0.1,
2428
+ 0.25,
2429
+ 0.5,
2430
+ 1
2431
+ ],
2432
+ registers: [
2433
+ registry
2434
+ ]
2435
+ });
2436
+ var mcpActiveSessions = new client.Gauge({
2437
+ name: "mcp_active_sessions",
2438
+ help: "Current number of active MCP sessions",
2439
+ registers: [
2440
+ registry
2441
+ ]
2442
+ });
2443
+ var mcpProxyErrorsTotal = new client.Counter({
2444
+ name: "mcp_proxy_errors_total",
2445
+ help: "Total number of MCP proxy errors",
2446
+ labelNames: [
2447
+ "endpoint",
2448
+ "error_type"
2449
+ ],
2450
+ registers: [
2451
+ registry
2452
+ ]
2453
+ });
2454
+ var sseConnectionsTotal = new client.Gauge({
2455
+ name: "sse_connections_total",
2456
+ help: "Current number of SSE connections",
2457
+ labelNames: [
2458
+ "service"
2459
+ ],
2460
+ registers: [
2461
+ registry
2462
+ ]
2463
+ });
2464
+ function recordHealthCheck(service, check, status, durationMs) {
2465
+ const isHealthy = status === "healthy" ? 1 : 0;
2466
+ healthCheckStatus.set({
2467
+ service,
2468
+ check
2469
+ }, isHealthy);
2470
+ healthCheckDurationSeconds.observe({
2471
+ service,
2472
+ check
2473
+ }, durationMs / 1e3);
2474
+ if (status === "healthy") {
2475
+ healthCheckLastSuccessTimestamp.set({
2476
+ service,
2477
+ check
2478
+ }, Date.now() / 1e3);
2479
+ }
2480
+ if (status === "unhealthy") {
2481
+ healthCheckFailuresTotal.inc({
2482
+ service,
2483
+ check,
2484
+ reason: "check_failed"
2485
+ });
2486
+ }
2487
+ }
2488
+ __name(recordHealthCheck, "recordHealthCheck");
2489
+ function recordReadinessProbe(service, isReady) {
2490
+ readinessProbeStatus.set({
2491
+ service
2492
+ }, isReady ? 1 : 0);
2493
+ if (isReady) {
2494
+ readinessProbeLastSuccessTimestamp.set({
2495
+ service
2496
+ }, Date.now() / 1e3);
2497
+ }
2498
+ }
2499
+ __name(recordReadinessProbe, "recordReadinessProbe");
2500
+ function recordStartupComplete(service, durationSeconds) {
2501
+ startupProbeDurationSeconds.set({
2502
+ service
2503
+ }, durationSeconds);
2504
+ }
2505
+ __name(recordStartupComplete, "recordStartupComplete");
2506
+ async function getMetrics() {
2507
+ return registry.metrics();
2508
+ }
2509
+ __name(getMetrics, "getMetrics");
2510
+ function getContentType() {
2511
+ return registry.contentType;
2512
+ }
2513
+ __name(getContentType, "getContentType");
2514
+
2515
+ // ../../packages/infrastructure/dist/sentry/index.js
2516
+ var Sentry = null;
2517
+ var ProfilingIntegration = null;
2518
+ async function loadSentry() {
2519
+ if (Sentry) {
2520
+ return {
2521
+ Sentry,
2522
+ ProfilingIntegration
2523
+ };
2524
+ }
2525
+ if (process.env.DISABLE_SENTRY === "true") {
2526
+ return null;
2527
+ }
2528
+ try {
2529
+ Sentry = await import('@sentry/node');
2530
+ ProfilingIntegration = await import('@sentry/profiling-node');
2531
+ return {
2532
+ Sentry,
2533
+ ProfilingIntegration
2534
+ };
2535
+ } catch (_error) {
2536
+ return null;
2537
+ }
2538
+ }
2539
+ __name(loadSentry, "loadSentry");
2540
+ async function initSentry(options) {
2541
+ if (process.env.DISABLE_SENTRY === "true" || options?.enabled === false) {
2542
+ process.stdout.write("\u2139\uFE0F Sentry is disabled");
2543
+ return;
2544
+ }
2545
+ const dsn = options?.dsn || process.env.SENTRY_DSN;
2546
+ if (!dsn) {
2547
+ return;
2548
+ }
2549
+ const modules = await loadSentry();
2550
+ if (!modules) {
2551
+ return;
2552
+ }
2553
+ const { Sentry: SentryModule, ProfilingIntegration: ProfilingIntegration2 } = modules;
2554
+ const HttpIntegration = SentryModule.Integrations?.Http ?? SentryModule.HttpIntegration;
2555
+ const integrations = [];
2556
+ if (HttpIntegration) {
2557
+ integrations.push(new HttpIntegration({
2558
+ tracing: true,
2559
+ request: true
2560
+ }));
2561
+ }
2562
+ if (ProfilingIntegration2) {
2563
+ integrations.push(ProfilingIntegration2.nodeProfilingIntegration());
2564
+ }
2565
+ SentryModule.init({
2566
+ dsn,
2567
+ environment: options?.environment || process.env.NODE_ENV || "development",
2568
+ release: options?.release || process.env.GIT_SHA || process.env.RELEASE || void 0,
2569
+ tracesSampleRate: options?.tracesSampleRate ?? (process.env.NODE_ENV === "production" ? 0.1 : 1),
2570
+ profilesSampleRate: options?.profilesSampleRate ?? 0.1,
2571
+ debug: options?.debug || process.env.DEBUG_SENTRY === "true",
2572
+ integrations,
2573
+ // Filter out sensitive data
2574
+ beforeSend: /* @__PURE__ */ __name((event, _hint) => {
2575
+ if (event.exception?.values?.[0]?.value?.includes?.("404") || event.request?.url?.includes?.("/favicon.ico")) {
2576
+ return null;
2577
+ }
2578
+ const request = event.request;
2579
+ if (request?.headers) {
2580
+ delete request.headers.authorization;
2581
+ delete request.headers.cookie;
2582
+ }
2583
+ return event;
2584
+ }, "beforeSend")
2585
+ });
2586
+ process.stdout.write("\u2705 Sentry initialized for error tracking");
2587
+ }
2588
+ __name(initSentry, "initSentry");
2589
+ function createSentryMiddleware() {
2590
+ if (!Sentry) {
2591
+ return {
2592
+ requestHandler: /* @__PURE__ */ __name((_c, next) => next(), "requestHandler"),
2593
+ errorHandler: /* @__PURE__ */ __name((_c, next) => next(), "errorHandler")
2594
+ };
2595
+ }
2596
+ const sentry = Sentry;
2597
+ return {
2598
+ requestHandler: sentry.Handlers?.requestHandler?.() || ((_c, next) => next()),
2599
+ errorHandler: sentry.Handlers?.errorHandler?.() || ((_c, next) => next())
2600
+ };
2601
+ }
2602
+ __name(createSentryMiddleware, "createSentryMiddleware");
2603
+ function captureError(error, context2) {
2604
+ if (process.env.DISABLE_SENTRY === "true" || !Sentry) {
2605
+ return;
2606
+ }
2607
+ Sentry.withScope((scope) => {
2608
+ if (context2) {
2609
+ if (context2.userId) {
2610
+ scope.setUser({
2611
+ id: context2.userId
2612
+ });
2613
+ }
2614
+ if (context2.organizationId) {
2615
+ scope.setTag("organization_id", context2.organizationId);
2616
+ }
2617
+ if (context2.tags) {
2618
+ Object.entries(context2.tags).forEach(([key, value]) => {
2619
+ scope.setTag(key, value);
2620
+ });
2621
+ }
2622
+ if (context2.extra) {
2623
+ scope.setContext("extra", context2.extra);
2624
+ }
2625
+ }
2626
+ if (Sentry) {
2627
+ Sentry.captureException(typeof error === "string" ? new Error(error) : error);
2628
+ }
2629
+ });
2630
+ }
2631
+ __name(captureError, "captureError");
2632
+ function captureMessage(message, level = "info", context2) {
2633
+ if (process.env.DISABLE_SENTRY === "true" || !Sentry) {
2634
+ return;
2635
+ }
2636
+ Sentry.captureMessage(message, level);
2637
+ if (context2) {
2638
+ Sentry.withScope((scope) => {
2639
+ if (context2.userId) {
2640
+ scope.setUser({
2641
+ id: context2.userId
2642
+ });
2643
+ }
2644
+ if (context2.tags) {
2645
+ Object.entries(context2.tags).forEach(([key, value]) => {
2646
+ scope.setTag(key, value);
2647
+ });
2648
+ }
2649
+ if (context2.extra) {
2650
+ scope.setContext("extra", context2.extra);
2651
+ }
2652
+ });
2653
+ }
2654
+ }
2655
+ __name(captureMessage, "captureMessage");
2656
+ function setSentryUser(userId, userInfo) {
2657
+ if (process.env.DISABLE_SENTRY === "true" || !Sentry) {
2658
+ return;
2659
+ }
2660
+ Sentry.setUser({
2661
+ id: userId,
2662
+ email: userInfo?.email,
2663
+ username: userInfo?.username,
2664
+ organization_id: userInfo?.organizationId
2665
+ });
2666
+ }
2667
+ __name(setSentryUser, "setSentryUser");
2668
+ function clearSentryUser() {
2669
+ if (process.env.DISABLE_SENTRY === "true" || !Sentry) {
2670
+ return;
2671
+ }
2672
+ Sentry.setUser(null);
2673
+ }
2674
+ __name(clearSentryUser, "clearSentryUser");
2675
+ function addSentryBreadcrumb(message, data, level = "info") {
2676
+ if (process.env.DISABLE_SENTRY === "true" || !Sentry) {
2677
+ return;
2678
+ }
2679
+ Sentry.addBreadcrumb({
2680
+ message,
2681
+ level,
2682
+ data,
2683
+ timestamp: Date.now() / 1e3
2684
+ });
2685
+ }
2686
+ __name(addSentryBreadcrumb, "addSentryBreadcrumb");
2687
+ function startSentryTransaction(name, op) {
2688
+ if (process.env.DISABLE_SENTRY === "true") {
2689
+ return null;
2690
+ }
2691
+ return Sentry.startTransaction?.({
2692
+ name,
2693
+ op: op || "operation"
2694
+ }) || null;
2695
+ }
2696
+ __name(startSentryTransaction, "startSentryTransaction");
2697
+ async function flushSentry(timeout = 2e3) {
2698
+ if (process.env.DISABLE_SENTRY === "true" || !Sentry) {
2699
+ return true;
2700
+ }
2701
+ return await Sentry.close(timeout);
2702
+ }
2703
+ __name(flushSentry, "flushSentry");
2704
+
2705
+ // ../../packages/infrastructure/dist/tracing/error-budget.js
2706
+ var ERROR_BUDGET = 0.01;
2707
+ var ALERT_THRESHOLD = 5e-3;
2708
+ var errorMetrics = {
2709
+ totalRequests: 0,
2710
+ errorCount: 0,
2711
+ lastAlertTime: 0
2712
+ };
2713
+ function recordSuccess() {
2714
+ errorMetrics.totalRequests++;
2715
+ }
2716
+ __name(recordSuccess, "recordSuccess");
2717
+ function recordError() {
2718
+ errorMetrics.totalRequests++;
2719
+ errorMetrics.errorCount++;
2720
+ }
2721
+ __name(recordError, "recordError");
2722
+ function getErrorRate() {
2723
+ if (errorMetrics.totalRequests === 0) {
2724
+ return 0;
2725
+ }
2726
+ return errorMetrics.errorCount / errorMetrics.totalRequests;
2727
+ }
2728
+ __name(getErrorRate, "getErrorRate");
2729
+ async function checkErrorBudget() {
2730
+ const errorRate = getErrorRate();
2731
+ if (errorRate > ALERT_THRESHOLD && Date.now() - errorMetrics.lastAlertTime > 6e4) {
2732
+ logger.warn({
2733
+ errorRate: `${(errorRate * 100).toFixed(2)}%`,
2734
+ threshold: `${(ALERT_THRESHOLD * 100).toFixed(2)}%`,
2735
+ errorCount: errorMetrics.errorCount,
2736
+ totalRequests: errorMetrics.totalRequests
2737
+ }, "Error rate approaching budget threshold");
2738
+ errorMetrics.lastAlertTime = Date.now();
2739
+ }
2740
+ if (errorRate > ERROR_BUDGET) {
2741
+ logger.error({
2742
+ errorRate: `${(errorRate * 100).toFixed(2)}%`,
2743
+ budget: `${(ERROR_BUDGET * 100).toFixed(2)}%`,
2744
+ errorCount: errorMetrics.errorCount,
2745
+ totalRequests: errorMetrics.totalRequests,
2746
+ recommendation: "Investigate root cause immediately and consider rolling back"
2747
+ }, "\u{1F6A8} Error budget exceeded!");
2748
+ await sendAlert({
2749
+ channel: "#alerts",
2750
+ message: `\u{1F6A8} Error budget exceeded! Current error rate: ${(errorRate * 100).toFixed(2)}% (Budget: ${(ERROR_BUDGET * 100).toFixed(2)}%)`
2751
+ });
2752
+ }
2753
+ }
2754
+ __name(checkErrorBudget, "checkErrorBudget");
2755
+ async function sendAlert(alert) {
2756
+ logger.info(alert, "Alert sent");
2757
+ }
2758
+ __name(sendAlert, "sendAlert");
2759
+ function resetMetrics() {
2760
+ errorMetrics.totalRequests = 0;
2761
+ errorMetrics.errorCount = 0;
2762
+ errorMetrics.lastAlertTime = 0;
2763
+ }
2764
+ __name(resetMetrics, "resetMetrics");
2765
+ function getMetrics2() {
2766
+ return {
2767
+ ...errorMetrics,
2768
+ errorRate: getErrorRate()
2769
+ };
2770
+ }
2771
+ __name(getMetrics2, "getMetrics");
2772
+ var OTelSpanAdapter = class OTelSpanAdapter2 {
2773
+ static {
2774
+ __name(this, "OTelSpanAdapter");
2775
+ }
2776
+ otelSpan;
2777
+ constructor(otelSpan) {
2778
+ this.otelSpan = otelSpan;
2779
+ }
2780
+ setAttribute(key, value) {
2781
+ this.otelSpan.setAttribute(key, value);
2782
+ }
2783
+ setAttributes(attributes) {
2784
+ this.otelSpan.setAttributes(attributes);
2785
+ }
2786
+ addEvent(name, attributes) {
2787
+ this.otelSpan.addEvent(name, attributes);
2788
+ }
2789
+ setStatus(status) {
2790
+ this.otelSpan.setStatus({
2791
+ code: status.code,
2792
+ message: status.message
2793
+ });
2794
+ }
2795
+ recordException(error) {
2796
+ this.otelSpan.recordException(error);
2797
+ }
2798
+ end() {
2799
+ this.otelSpan.end();
2800
+ }
2801
+ isRecording() {
2802
+ return this.otelSpan.isRecording();
2803
+ }
2804
+ };
2805
+ var OTelInstrumentationProvider = class {
2806
+ static {
2807
+ __name(this, "OTelInstrumentationProvider");
2808
+ }
2809
+ tracer;
2810
+ provider;
2811
+ meter;
2812
+ constructor(config) {
2813
+ const resource = resourceFromAttributes({
2814
+ [ATTR_SERVICE_NAME]: config.serviceName,
2815
+ [ATTR_SERVICE_VERSION]: config.serviceVersion || "unknown",
2816
+ "deployment.environment": config.environment || "development",
2817
+ "service.instance.id": process.pid.toString(),
2818
+ "host.name": process.env.HOSTNAME || "unknown",
2819
+ "process.pid": process.pid
2820
+ });
2821
+ const spanProcessors = [];
2822
+ if (config.collectorUrl) {
2823
+ const otlpExporter = new OTLPTraceExporter({
2824
+ url: config.collectorUrl
2825
+ });
2826
+ spanProcessors.push(new BatchSpanProcessor(otlpExporter));
2827
+ }
2828
+ if (config.enableConsole) {
2829
+ const consoleExporter = new ConsoleSpanExporter();
2830
+ spanProcessors.push(new BatchSpanProcessor(consoleExporter));
2831
+ }
2832
+ const samplingRate = config.sampleRate ?? 1;
2833
+ const sampler = new TraceIdRatioBasedSampler(samplingRate);
2834
+ this.provider = new NodeTracerProvider({
2835
+ resource,
2836
+ sampler,
2837
+ spanProcessors
2838
+ });
2839
+ this.provider.register();
2840
+ const pinoInstrumentation = new PinoInstrumentation({
2841
+ // Keep default log keys: trace_id, span_id, trace_flags
2842
+ // These match standard OTel semantic conventions
2843
+ disableLogSending: true,
2844
+ disableLogCorrelation: false
2845
+ });
2846
+ const pgInstrumentation = new PgInstrumentation({
2847
+ // Add database query attributes to spans
2848
+ requireParentSpan: false,
2849
+ enhancedDatabaseReporting: true
2850
+ });
2851
+ try {
2852
+ pinoInstrumentation.enable();
2853
+ pgInstrumentation.enable();
2854
+ } catch {
2855
+ }
2856
+ this.tracer = trace.getTracer(config.serviceName, config.serviceVersion);
2857
+ this.meter = metrics.getMeter(config.serviceName, config.serviceVersion || "unknown");
2858
+ try {
2859
+ if (config.collectorUrl) {
2860
+ const metricsUrl = config.collectorUrl.replace("/traces", "/metrics");
2861
+ const metricReader = new PeriodicExportingMetricReader({
2862
+ exporter: new OTLPMetricExporter({
2863
+ url: metricsUrl
2864
+ }),
2865
+ exportIntervalMillis: 6e4
2866
+ });
2867
+ const meterProvider = new MeterProvider({
2868
+ resource,
2869
+ readers: [
2870
+ metricReader
2871
+ ]
2872
+ });
2873
+ metrics.setGlobalMeterProvider(meterProvider);
2874
+ }
2875
+ } catch (_error) {
2876
+ }
2877
+ }
2878
+ startSpan(name, options) {
2879
+ const otelSpan = this.tracer.startSpan(name, {
2880
+ kind: options?.kind,
2881
+ attributes: options?.attributes,
2882
+ startTime: options?.startTime
2883
+ });
2884
+ return new OTelSpanAdapter(otelSpan);
2885
+ }
2886
+ async withSpan(name, fn, options) {
2887
+ const parentCtx = options?.parent ? options.parent : context.active();
2888
+ return await this.tracer.startActiveSpan(name, {
2889
+ kind: options?.kind,
2890
+ attributes: options?.attributes,
2891
+ startTime: options?.startTime
2892
+ }, parentCtx, async (otelSpan) => {
2893
+ const span = new OTelSpanAdapter(otelSpan);
2894
+ try {
2895
+ const result = await fn(span);
2896
+ otelSpan.setStatus({
2897
+ code: SpanStatusCode.OK
2898
+ });
2899
+ return result;
2900
+ } catch (error) {
2901
+ otelSpan.recordException(error);
2902
+ otelSpan.setStatus({
2903
+ code: SpanStatusCode.ERROR,
2904
+ message: error instanceof Error ? error.message : String(error)
2905
+ });
2906
+ throw error;
2907
+ } finally {
2908
+ otelSpan.end();
2909
+ }
2910
+ });
2911
+ }
2912
+ injectContext(carrier) {
2913
+ propagation.inject(context.active(), carrier);
2914
+ }
2915
+ extractContext(carrier) {
2916
+ const extractedContext = propagation.extract(ROOT_CONTEXT, carrier);
2917
+ const span = trace.getSpan(extractedContext);
2918
+ if (span?.spanContext().traceId) {
2919
+ return extractedContext;
2920
+ }
2921
+ return null;
2922
+ }
2923
+ recordMetric(name, value, attributes) {
2924
+ const counter = this.meter.createCounter(name);
2925
+ counter.add(value, attributes);
2926
+ }
2927
+ recordEvent(_name, _attributes) {
2928
+ }
2929
+ async shutdown() {
2930
+ await this.provider.shutdown();
2931
+ }
2932
+ };
2933
+
2934
+ // ../../packages/infrastructure/dist/tracing/telemetry-client.js
2935
+ var TelemetryClient = class {
2936
+ static {
2937
+ __name(this, "TelemetryClient");
2938
+ }
2939
+ environment;
2940
+ flags = /* @__PURE__ */ new Map();
2941
+ eventQueue = [];
2942
+ flushInterval = 5e3;
2943
+ maxQueueSize = 100;
2944
+ rateLimitWindow = 6e4;
2945
+ eventCounts = /* @__PURE__ */ new Map();
2946
+ lastRateLimitReset = Date.now();
2947
+ proxyUrl;
2948
+ offlineMode = false;
2949
+ anonymousId;
2950
+ constructor(_apiKey, proxyHost, environment) {
2951
+ this.environment = environment;
2952
+ this.proxyUrl = `${proxyHost}/api/telemetry/events`;
2953
+ this.anonymousId = this.generateAnonymousId();
2954
+ setInterval(() => this.flush(), this.flushInterval);
2955
+ }
2956
+ async initialize() {
2957
+ }
2958
+ /**
2959
+ * Set offline mode
2960
+ * @param enabled Whether offline mode is enabled
2961
+ */
2962
+ setOfflineMode(enabled) {
2963
+ this.offlineMode = enabled;
2964
+ }
2965
+ /**
2966
+ * Check if offline mode is enabled
2967
+ * @returns Whether offline mode is enabled
2968
+ */
2969
+ isOfflineMode() {
2970
+ return this.offlineMode;
2971
+ }
2972
+ isEnabled(flag) {
2973
+ const value = this.flags.get(flag) ?? FEATURE_FLAGS[flag];
2974
+ return Boolean(value);
2975
+ }
2976
+ async reloadFlags() {
2977
+ }
2978
+ /**
2979
+ * Track a telemetry event with strict typing and validation
2980
+ * @param event The event name (must be from the whitelist)
2981
+ * @param properties The event properties (validated at runtime)
2982
+ */
2983
+ trackEvent(event) {
2984
+ if (!validateTelemetryEvent(event)) {
2985
+ console.warn("Invalid telemetry event, skipping:", event);
2986
+ return;
2987
+ }
2988
+ if (this.offlineMode) {
2989
+ return;
2990
+ }
2991
+ const featureManager = FeatureManager.getInstance();
2992
+ if (!featureManager.isEnabled("telemetry.detailed_events")) {
2993
+ if (![
2994
+ "checkpoint.created",
2995
+ "risk.high",
2996
+ "error"
2997
+ ].includes(event.event)) {
2998
+ return;
2999
+ }
3000
+ }
3001
+ const samplingRate = featureManager.getValue("telemetry.sampling_rate") ?? 1;
3002
+ if (Math.random() > samplingRate) {
3003
+ return;
3004
+ }
3005
+ if (this.isRateLimited(event.event)) {
3006
+ return;
3007
+ }
3008
+ this.eventQueue.push({
3009
+ event: event.event,
3010
+ properties: {
3011
+ ...this.sanitizeProperties(event.properties || {}),
3012
+ environment: this.environment,
3013
+ timestamp: event.timestamp
3014
+ },
3015
+ timestamp: event.timestamp
3016
+ });
3017
+ if (this.eventQueue.length >= this.maxQueueSize) {
3018
+ this.flush();
3019
+ }
3020
+ }
3021
+ /**
3022
+ * Track a telemetry event with string-based event name (legacy compatibility)
3023
+ * @param event The event name
3024
+ * @param properties The event properties
3025
+ */
3026
+ track(event, properties) {
3027
+ const typedEvent = {
3028
+ event,
3029
+ properties,
3030
+ timestamp: Date.now()
3031
+ };
3032
+ this.trackEvent(typedEvent);
3033
+ }
3034
+ isRateLimited(event) {
3035
+ const now = Date.now();
3036
+ if (now - this.lastRateLimitReset > this.rateLimitWindow) {
3037
+ this.eventCounts.clear();
3038
+ this.lastRateLimitReset = now;
3039
+ }
3040
+ const count = this.eventCounts.get(event) || 0;
3041
+ const maxEventsPerWindow = 10;
3042
+ if (count >= maxEventsPerWindow) {
3043
+ return true;
3044
+ }
3045
+ this.eventCounts.set(event, count + 1);
3046
+ return false;
3047
+ }
3048
+ /**
3049
+ * Sanitize properties to remove PII before sending
3050
+ */
3051
+ sanitizeProperties(properties) {
3052
+ const sanitized = {};
3053
+ if (!properties) {
3054
+ return sanitized;
3055
+ }
3056
+ const allowedProps = [
3057
+ "version",
3058
+ "platform",
3059
+ "duration",
3060
+ "success",
3061
+ "filesCount",
3062
+ "method",
3063
+ "trigger",
3064
+ "feature",
3065
+ "viewId",
3066
+ "command"
3067
+ ];
3068
+ for (const key of allowedProps) {
3069
+ if (key in properties) {
3070
+ sanitized[key] = properties[key];
3071
+ }
3072
+ }
3073
+ return sanitized;
3074
+ }
3075
+ /**
3076
+ * Get the anonymous ID for this client instance
3077
+ * @returns The stored anonymous ID
3078
+ */
3079
+ getAnonymousId() {
3080
+ return this.anonymousId;
3081
+ }
3082
+ generateAnonymousId() {
3083
+ return `${this.environment}_${Math.random().toString(36).substr(2, 9)}`;
3084
+ }
3085
+ /**
3086
+ * Get current package version
3087
+ * @returns The current version string
3088
+ */
3089
+ getVersion() {
3090
+ try {
3091
+ const packageJson = require_package();
3092
+ return packageJson.version || "unknown";
3093
+ } catch (_error) {
3094
+ return process.env.VREKO_VERSION || "1.0.0";
3095
+ }
3096
+ }
3097
+ /**
3098
+ * Custom transport layer - routes all events through proxy
3099
+ */
3100
+ async customTransport(batch) {
3101
+ if (this.offlineMode) {
3102
+ return;
3103
+ }
3104
+ try {
3105
+ const response = await fetch(this.proxyUrl, {
3106
+ method: "POST",
3107
+ headers: {
3108
+ "Content-Type": "application/json",
3109
+ "X-Vreko-Platform": this.environment,
3110
+ "X-Vreko-Version": this.getVersion()
3111
+ },
3112
+ body: JSON.stringify({
3113
+ events: batch.map((event) => ({
3114
+ event: event.event,
3115
+ properties: this.sanitizeProperties(event.properties || {}),
3116
+ timestamp: event.timestamp
3117
+ }))
3118
+ })
3119
+ });
3120
+ if (!response.ok) {
3121
+ const _error = await response.text();
3122
+ }
3123
+ } catch (_error) {
3124
+ }
3125
+ }
3126
+ async flush() {
3127
+ if (this.offlineMode) {
3128
+ return;
3129
+ }
3130
+ if (this.eventQueue.length === 0) {
3131
+ return;
3132
+ }
3133
+ const eventsToFlush = [
3134
+ ...this.eventQueue
3135
+ ];
3136
+ this.eventQueue = [];
3137
+ try {
3138
+ await this.customTransport(eventsToFlush);
3139
+ } catch (_error) {
3140
+ this.eventQueue.unshift(...eventsToFlush);
3141
+ }
3142
+ }
3143
+ };
3144
+
3145
+ export { AgentAction, AgentRole, AgentSession, AnalyticsEvents, CORRELATION_ANALYSES, CORRELATION_COHORTS, KEY_METRIC_ALERTS, OTelInstrumentationProvider, RETENTION_COHORTS, TelemetryClient, addSentryBreadcrumb, attributionChain, captureError, captureMessage, checkDatabaseConnection, checkErrorBudget, checkHttpService, checkRedisConnection, clearSentryUser, conductorSessionInsights, createAlert, createCohort, createGracefulShutdown, createHealthCheck, createSentryMiddleware, decisionsWithSkips, deleteAlert, deleteCohort, detectSurface, drainAndCloseServer, emitPhaseEvent, emitRatchetScores, failedGatesInLastNRuns, flushSentry, gatesFailingFirstAttempt, getAlerts, getAnalyticsEnv, getAnalyticsSuperProperties, getCohort, getCohortMembers, getCohorts, getCorrelationAnalysis, getDeploymentEnv, getEnvironmentInfo, getErrorRate, getMetrics2 as getMetrics, gitCommitsWithoutProvenance, initSentry, isDevelopment, isProduction, neon_exports, performCorrelationAnalysis, preStopDelay, prometheus_exports, recordAction, recordDecision, recordError, recordGate, recordSuccess, registerKeyMetricAlerts, resetMetrics, setSentryUser, startSentryTransaction, toggleAlert, updateCohort, validateMetadata };
3146
+ //# sourceMappingURL=chunk-A3QSZJPD.js.map
3147
+ //# sourceMappingURL=chunk-A3QSZJPD.js.map