brakit 0.8.7 → 0.9.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +15 -3
- package/dist/api.d.ts +83 -46
- package/dist/api.js +776 -767
- package/dist/bin/brakit.js +305 -432
- 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 +1566 -1700
- 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
|
}
|
|
@@ -382,74 +391,102 @@ interface CaptureInput {
|
|
|
382
391
|
endTime?: number;
|
|
383
392
|
config: Pick<BrakitConfig, "maxBodyCapture">;
|
|
384
393
|
}
|
|
385
|
-
|
|
386
|
-
|
|
387
|
-
|
|
388
|
-
|
|
394
|
+
declare class RequestStore {
|
|
395
|
+
private maxEntries;
|
|
396
|
+
private requests;
|
|
397
|
+
private listeners;
|
|
398
|
+
constructor(maxEntries?: number);
|
|
399
|
+
capture(input: CaptureInput): TracedRequest;
|
|
400
|
+
add(entry: TracedRequest): void;
|
|
401
|
+
getAll(): readonly TracedRequest[];
|
|
402
|
+
clear(): void;
|
|
403
|
+
onRequest(fn: RequestListener): void;
|
|
404
|
+
offRequest(fn: RequestListener): void;
|
|
389
405
|
}
|
|
390
|
-
|
|
406
|
+
|
|
407
|
+
type TelemetryListener<T> = (entry: T) => void;
|
|
408
|
+
/** Read-only view of a TelemetryStore — used by API handlers that only query data. */
|
|
409
|
+
interface ReadonlyTelemetryStore {
|
|
410
|
+
getAll(): readonly TelemetryEntry[];
|
|
411
|
+
getByRequest(requestId: string): TelemetryEntry[];
|
|
412
|
+
}
|
|
413
|
+
declare class TelemetryStore<T extends TelemetryEntry> implements ReadonlyTelemetryStore {
|
|
414
|
+
private maxEntries;
|
|
415
|
+
private entries;
|
|
416
|
+
private listeners;
|
|
417
|
+
constructor(maxEntries?: number);
|
|
391
418
|
add(data: Omit<T, "id">): T;
|
|
392
419
|
getAll(): readonly T[];
|
|
393
420
|
getByRequest(requestId: string): T[];
|
|
394
421
|
clear(): void;
|
|
422
|
+
onEntry(fn: TelemetryListener<T>): void;
|
|
423
|
+
offEntry(fn: TelemetryListener<T>): void;
|
|
395
424
|
}
|
|
396
|
-
|
|
397
|
-
|
|
398
|
-
|
|
399
|
-
|
|
400
|
-
|
|
425
|
+
|
|
426
|
+
interface MetricsPersistence {
|
|
427
|
+
load(): MetricsData;
|
|
428
|
+
loadAsync(): Promise<MetricsData>;
|
|
429
|
+
save(data: MetricsData): void;
|
|
430
|
+
saveSync(data: MetricsData): void;
|
|
431
|
+
remove(): void;
|
|
401
432
|
}
|
|
402
|
-
|
|
433
|
+
|
|
434
|
+
declare class MetricsStore {
|
|
435
|
+
private persistence;
|
|
436
|
+
private data;
|
|
437
|
+
private endpointIndex;
|
|
438
|
+
private sessionId;
|
|
439
|
+
private sessionStart;
|
|
440
|
+
private flushTimer;
|
|
441
|
+
private dirty;
|
|
442
|
+
private accumulators;
|
|
443
|
+
private pendingPoints;
|
|
444
|
+
constructor(persistence: MetricsPersistence);
|
|
445
|
+
start(): void;
|
|
446
|
+
stop(): void;
|
|
403
447
|
recordRequest(req: TracedRequest, metrics: RequestMetrics): void;
|
|
404
448
|
getAll(): readonly EndpointMetrics[];
|
|
405
449
|
getEndpoint(endpoint: string): EndpointMetrics | undefined;
|
|
450
|
+
/**
|
|
451
|
+
* Compute the adaptive performance baseline for an endpoint.
|
|
452
|
+
* Returns the median p95 across historical sessions, or null when
|
|
453
|
+
* there isn't enough data to establish a meaningful baseline.
|
|
454
|
+
*/
|
|
455
|
+
/**
|
|
456
|
+
* Cached baselines — invalidated on flush (when sessions change) and
|
|
457
|
+
* on new request recordings (when pending points grow). Avoids recomputing
|
|
458
|
+
* on every getLiveEndpoints() API call.
|
|
459
|
+
*/
|
|
460
|
+
private baselineCache;
|
|
461
|
+
getEndpointBaseline(endpoint: string): number | null;
|
|
462
|
+
private computeBaseline;
|
|
406
463
|
getLiveEndpoints(): LiveEndpointData[];
|
|
407
464
|
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[];
|
|
465
|
+
flush(sync?: boolean): void;
|
|
466
|
+
private getOrCreateEndpoint;
|
|
424
467
|
}
|
|
425
468
|
|
|
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;
|
|
469
|
+
interface Services {
|
|
470
|
+
bus: EventBus;
|
|
471
|
+
requestStore: RequestStore;
|
|
472
|
+
queryStore: TelemetryStore<TracedQuery>;
|
|
473
|
+
fetchStore: TelemetryStore<TracedFetch>;
|
|
474
|
+
logStore: TelemetryStore<TracedLog>;
|
|
475
|
+
errorStore: TelemetryStore<TracedError>;
|
|
476
|
+
metricsStore: MetricsStore;
|
|
477
|
+
issueStore: IssueStore;
|
|
478
|
+
analysisEngine: AnalysisEngine;
|
|
442
479
|
}
|
|
443
480
|
|
|
444
481
|
declare class AnalysisEngine {
|
|
445
|
-
private
|
|
482
|
+
private services;
|
|
446
483
|
private debounceMs;
|
|
447
484
|
private scanner;
|
|
448
485
|
private cachedInsights;
|
|
449
486
|
private cachedFindings;
|
|
450
487
|
private debounceTimer;
|
|
451
488
|
private subs;
|
|
452
|
-
constructor(
|
|
489
|
+
constructor(services: Services, debounceMs?: number);
|
|
453
490
|
start(): void;
|
|
454
491
|
stop(): void;
|
|
455
492
|
getInsights(): readonly Insight[];
|