brakit 0.8.7 → 0.9.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.
package/README.md CHANGED
@@ -52,19 +52,31 @@
52
52
 
53
53
  ## Quick Start
54
54
 
55
+ ### Node.js
56
+
55
57
  ```bash
56
58
  npx brakit install
59
+ npm run dev
57
60
  ```
58
61
 
59
- That's it. Brakit detects your framework, adds itself as a devDependency, and creates the instrumentation file. Start your app normally:
62
+ ### Python (FastAPI / Flask)
60
63
 
61
64
  ```bash
62
- npm run dev
65
+ pip install brakit
66
+ ```
67
+
68
+ ```python
69
+ import brakit # must be before framework import
70
+ from fastapi import FastAPI
71
+
72
+ app = FastAPI()
63
73
  ```
64
74
 
65
75
  Dashboard at `http://localhost:<port>/__brakit`. Issues in the terminal.
66
76
 
67
- > **Requirements:** Node.js >= 18 and a project with `package.json`.
77
+ > **Full setup guide:** [brakit.ai/docs/introduction](https://brakit.ai/docs/introduction)
78
+
79
+ > **Requirements:** Node.js >= 18. Python SDK requires Python >= 3.9.
68
80
 
69
81
  ---
70
82
 
package/dist/api.d.ts CHANGED
@@ -16,6 +16,7 @@ interface TracedRequest {
16
16
  durationMs: number;
17
17
  responseSize: number;
18
18
  isStatic: boolean;
19
+ isHealthCheck: boolean;
19
20
  }
20
21
  type RequestListener = (req: TracedRequest) => void;
21
22
 
@@ -35,7 +36,7 @@ interface BrakitConfig {
35
36
  customCommand?: string;
36
37
  }
37
38
 
38
- type RequestCategory = "auth-handshake" | "auth-check" | "middleware" | "server-action" | "api-call" | "data-fetch" | "page-load" | "navigation" | "polling" | "static" | "unknown";
39
+ type RequestCategory = "auth-handshake" | "auth-check" | "health-check" | "middleware" | "server-action" | "api-call" | "data-fetch" | "page-load" | "navigation" | "polling" | "static" | "unknown";
39
40
  interface LabeledRequest extends TracedRequest {
40
41
  label: string;
41
42
  category: RequestCategory;
@@ -121,6 +122,10 @@ interface EndpointMetrics {
121
122
  sessions: SessionMetric[];
122
123
  dataPoints?: LiveRequestPoint[];
123
124
  }
125
+ interface MetricsData {
126
+ version: 1;
127
+ endpoints: EndpointMetrics[];
128
+ }
124
129
  interface LiveRequestPoint {
125
130
  timestamp: number;
126
131
  durationMs: number;
@@ -131,6 +136,7 @@ interface LiveRequestPoint {
131
136
  }
132
137
  interface LiveEndpointSummary {
133
138
  p95Ms: number;
139
+ medianMs: number;
134
140
  errorRate: number;
135
141
  avgQueryCount: number;
136
142
  totalRequests: number;
@@ -142,6 +148,8 @@ interface LiveEndpointData {
142
148
  endpoint: string;
143
149
  requests: LiveRequestPoint[];
144
150
  summary: LiveEndpointSummary;
151
+ sessions?: SessionMetric[];
152
+ baselineP95Ms: number | null;
145
153
  }
146
154
  interface RequestMetrics {
147
155
  queryCount: number;
@@ -158,6 +166,7 @@ interface SecurityFinding {
158
166
  title: string;
159
167
  desc: string;
160
168
  hint: string;
169
+ detail?: string;
161
170
  endpoint: string;
162
171
  count: number;
163
172
  }
@@ -339,10 +348,12 @@ declare function detectProject(rootDir: string): Promise<DetectedProject>;
339
348
  declare class AdapterRegistry {
340
349
  private adapters;
341
350
  private active;
351
+ private failed;
342
352
  register(adapter: BrakitAdapter): void;
343
353
  patchAll(emit: (event: TelemetryEvent) => void): void;
344
354
  unpatchAll(): void;
345
355
  getActive(): readonly BrakitAdapter[];
356
+ getFailed(): readonly string[];
346
357
  }
347
358
 
348
359
  interface AnalysisUpdate {
@@ -382,74 +393,102 @@ interface CaptureInput {
382
393
  endTime?: number;
383
394
  config: Pick<BrakitConfig, "maxBodyCapture">;
384
395
  }
385
-
386
- interface Lifecycle {
387
- start(): void;
388
- stop(): void;
396
+ declare class RequestStore {
397
+ private maxEntries;
398
+ private requests;
399
+ private listeners;
400
+ constructor(maxEntries?: number);
401
+ capture(input: CaptureInput): TracedRequest;
402
+ add(entry: TracedRequest): void;
403
+ getAll(): readonly TracedRequest[];
404
+ clear(): void;
405
+ onRequest(fn: RequestListener): void;
406
+ offRequest(fn: RequestListener): void;
389
407
  }
390
- interface TelemetryStoreInterface<T extends TelemetryEntry> {
408
+
409
+ type TelemetryListener<T> = (entry: T) => void;
410
+ /** Read-only view of a TelemetryStore — used by API handlers that only query data. */
411
+ interface ReadonlyTelemetryStore {
412
+ getAll(): readonly TelemetryEntry[];
413
+ getByRequest(requestId: string): TelemetryEntry[];
414
+ }
415
+ declare class TelemetryStore<T extends TelemetryEntry> implements ReadonlyTelemetryStore {
416
+ private maxEntries;
417
+ private entries;
418
+ private listeners;
419
+ constructor(maxEntries?: number);
391
420
  add(data: Omit<T, "id">): T;
392
421
  getAll(): readonly T[];
393
422
  getByRequest(requestId: string): T[];
394
423
  clear(): void;
424
+ onEntry(fn: TelemetryListener<T>): void;
425
+ offEntry(fn: TelemetryListener<T>): void;
395
426
  }
396
- interface RequestStoreInterface {
397
- capture(input: CaptureInput): TracedRequest;
398
- add(entry: TracedRequest): void;
399
- getAll(): readonly TracedRequest[];
400
- clear(): void;
427
+
428
+ interface MetricsPersistence {
429
+ load(): MetricsData;
430
+ loadAsync(): Promise<MetricsData>;
431
+ save(data: MetricsData): void;
432
+ saveSync(data: MetricsData): void;
433
+ remove(): void;
401
434
  }
402
- interface MetricsStoreInterface extends Lifecycle {
435
+
436
+ declare class MetricsStore {
437
+ private persistence;
438
+ private data;
439
+ private endpointIndex;
440
+ private sessionId;
441
+ private sessionStart;
442
+ private flushTimer;
443
+ private dirty;
444
+ private accumulators;
445
+ private pendingPoints;
446
+ constructor(persistence: MetricsPersistence);
447
+ start(): void;
448
+ stop(): void;
403
449
  recordRequest(req: TracedRequest, metrics: RequestMetrics): void;
404
450
  getAll(): readonly EndpointMetrics[];
405
451
  getEndpoint(endpoint: string): EndpointMetrics | undefined;
452
+ /**
453
+ * Compute the adaptive performance baseline for an endpoint.
454
+ * Returns the median p95 across historical sessions, or null when
455
+ * there isn't enough data to establish a meaningful baseline.
456
+ */
457
+ /**
458
+ * Cached baselines — invalidated on flush (when sessions change) and
459
+ * on new request recordings (when pending points grow). Avoids recomputing
460
+ * on every getLiveEndpoints() API call.
461
+ */
462
+ private baselineCache;
463
+ getEndpointBaseline(endpoint: string): number | null;
464
+ private computeBaseline;
406
465
  getLiveEndpoints(): LiveEndpointData[];
407
466
  reset(): void;
408
- }
409
- interface IssueStoreInterface extends Lifecycle {
410
- upsert(issue: Issue, source: IssueSource): StatefulIssue;
411
- transition(issueId: string, state: IssueState): boolean;
412
- reportFix(issueId: string, status: AiFixStatus, notes: string): boolean;
413
- reconcile(currentIssueIds: Set<string>, activeEndpoints: Set<string>): void;
414
- getAll(): readonly StatefulIssue[];
415
- getByState(state: IssueState): readonly StatefulIssue[];
416
- getByCategory(category: IssueCategory): readonly StatefulIssue[];
417
- get(issueId: string): StatefulIssue | undefined;
418
- clear(): void;
419
- }
420
- interface AnalysisEngineInterface extends Lifecycle {
421
- recompute(): void;
422
- getInsights(): readonly Insight[];
423
- getFindings(): readonly SecurityFinding[];
467
+ flush(sync?: boolean): void;
468
+ private getOrCreateEndpoint;
424
469
  }
425
470
 
426
- interface ServiceMap {
427
- "event-bus": EventBus;
428
- "request-store": RequestStoreInterface;
429
- "query-store": TelemetryStoreInterface<TracedQuery>;
430
- "fetch-store": TelemetryStoreInterface<TracedFetch>;
431
- "log-store": TelemetryStoreInterface<TracedLog>;
432
- "error-store": TelemetryStoreInterface<TracedError>;
433
- "metrics-store": MetricsStoreInterface;
434
- "issue-store": IssueStoreInterface;
435
- "analysis-engine": AnalysisEngineInterface;
436
- }
437
- declare class ServiceRegistry {
438
- private services;
439
- register<K extends keyof ServiceMap>(name: K, service: ServiceMap[K]): void;
440
- get<K extends keyof ServiceMap>(name: K): ServiceMap[K];
441
- has<K extends keyof ServiceMap>(name: K): boolean;
471
+ interface Services {
472
+ bus: EventBus;
473
+ requestStore: RequestStore;
474
+ queryStore: TelemetryStore<TracedQuery>;
475
+ fetchStore: TelemetryStore<TracedFetch>;
476
+ logStore: TelemetryStore<TracedLog>;
477
+ errorStore: TelemetryStore<TracedError>;
478
+ metricsStore: MetricsStore;
479
+ issueStore: IssueStore;
480
+ analysisEngine: AnalysisEngine;
442
481
  }
443
482
 
444
483
  declare class AnalysisEngine {
445
- private registry;
484
+ private services;
446
485
  private debounceMs;
447
486
  private scanner;
448
487
  private cachedInsights;
449
488
  private cachedFindings;
450
489
  private debounceTimer;
451
490
  private subs;
452
- constructor(registry: ServiceRegistry, debounceMs?: number);
491
+ constructor(services: Services, debounceMs?: number);
453
492
  start(): void;
454
493
  stop(): void;
455
494
  getInsights(): readonly Insight[];