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 +15 -3
- package/dist/api.d.ts +85 -46
- package/dist/api.js +782 -767
- package/dist/bin/brakit.js +456 -450
- package/dist/dashboard-client.global.js +465 -267
- package/dist/dashboard.html +584 -310
- package/dist/mcp/server.js +7 -15
- package/dist/runtime/index.js +1747 -1770
- package/package.json +1 -1
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
|
-
|
|
62
|
+
### Python (FastAPI / Flask)
|
|
60
63
|
|
|
61
64
|
```bash
|
|
62
|
-
|
|
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
|
-
> **
|
|
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
|
-
|
|
387
|
-
|
|
388
|
-
|
|
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
|
-
|
|
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
|
-
|
|
397
|
-
|
|
398
|
-
|
|
399
|
-
|
|
400
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
|
427
|
-
|
|
428
|
-
|
|
429
|
-
|
|
430
|
-
|
|
431
|
-
|
|
432
|
-
|
|
433
|
-
|
|
434
|
-
|
|
435
|
-
|
|
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
|
|
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(
|
|
491
|
+
constructor(services: Services, debounceMs?: number);
|
|
453
492
|
start(): void;
|
|
454
493
|
stop(): void;
|
|
455
494
|
getInsights(): readonly Insight[];
|