pi-lens 3.2.0 → 3.3.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/CHANGELOG.md +20 -0
- package/README.md +4 -10
- package/clients/__tests__/file-time.test.js +216 -0
- package/clients/__tests__/format-service.test.js +245 -0
- package/clients/__tests__/formatters.test.js +271 -0
- package/clients/agent-behavior-client.test.js +94 -0
- package/clients/biome-client.test.js +144 -0
- package/clients/cache-manager.test.js +197 -0
- package/clients/complexity-client.test.js +234 -0
- package/clients/dependency-checker.test.js +60 -0
- package/clients/dispatch/__tests__/autofix-integration.test.js +245 -0
- package/clients/dispatch/__tests__/runner-registration.test.js +234 -0
- package/clients/dispatch/__tests__/runner-registration.test.ts +2 -2
- package/clients/dispatch/dispatcher.edge.test.js +82 -0
- package/clients/dispatch/dispatcher.format.test.js +46 -0
- package/clients/dispatch/dispatcher.inline.test.js +74 -0
- package/clients/dispatch/dispatcher.test.js +116 -0
- package/clients/dispatch/runners/architect.test.js +138 -0
- package/clients/dispatch/runners/ast-grep-napi.test.js +106 -0
- package/clients/dispatch/runners/lsp.js +42 -5
- package/clients/dispatch/runners/oxlint.test.js +230 -0
- package/clients/dispatch/runners/pyright.test.js +98 -0
- package/clients/dispatch/runners/python-slop.test.js +203 -0
- package/clients/dispatch/runners/scan_codebase.test.js +89 -0
- package/clients/dispatch/runners/shellcheck.test.js +98 -0
- package/clients/dispatch/runners/spellcheck.test.js +158 -0
- package/clients/dispatch/utils/format-utils.js +1 -6
- package/clients/dispatch/utils/format-utils.ts +1 -6
- package/clients/dogfood.test.js +201 -0
- package/clients/file-kinds.test.js +169 -0
- package/clients/formatters.js +1 -1
- package/clients/go-client.test.js +127 -0
- package/clients/jscpd-client.test.js +127 -0
- package/clients/knip-client.test.js +112 -0
- package/clients/lsp/__tests__/client.test.js +310 -0
- package/clients/lsp/__tests__/client.test.ts +1 -46
- package/clients/lsp/__tests__/config.test.js +167 -0
- package/clients/lsp/__tests__/error-recovery.test.js +213 -0
- package/clients/lsp/__tests__/integration.test.js +127 -0
- package/clients/lsp/__tests__/launch.test.js +313 -0
- package/clients/lsp/__tests__/server.test.js +259 -0
- package/clients/lsp/__tests__/service.test.js +435 -0
- package/clients/lsp/client.js +32 -44
- package/clients/lsp/client.ts +36 -45
- package/clients/lsp/launch.js +11 -6
- package/clients/lsp/launch.ts +11 -6
- package/clients/lsp/server.js +27 -2
- package/clients/metrics-client.test.js +141 -0
- package/clients/ruff-client.test.js +132 -0
- package/clients/rust-client.test.js +108 -0
- package/clients/sanitize.test.js +177 -0
- package/clients/secrets-scanner.test.js +100 -0
- package/clients/test-runner-client.test.js +192 -0
- package/clients/todo-scanner.test.js +301 -0
- package/clients/type-coverage-client.test.js +105 -0
- package/clients/typescript-client.codefix.test.js +157 -0
- package/clients/typescript-client.test.js +105 -0
- package/commands/rate.test.js +119 -0
- package/index.ts +66 -72
- package/package.json +1 -1
- package/clients/bus/bus.js +0 -191
- package/clients/bus/bus.ts +0 -251
- package/clients/bus/events.js +0 -214
- package/clients/bus/events.ts +0 -279
- package/clients/bus/index.js +0 -8
- package/clients/bus/index.ts +0 -9
- package/clients/bus/integration.js +0 -158
- package/clients/bus/integration.ts +0 -227
- package/clients/dispatch/bus-dispatcher.js +0 -178
- package/clients/dispatch/bus-dispatcher.ts +0 -258
- package/clients/services/__tests__/effect-integration.test.ts +0 -111
- package/clients/services/effect-integration.js +0 -198
- package/clients/services/effect-integration.ts +0 -276
- package/clients/services/index.js +0 -7
- package/clients/services/index.ts +0 -8
- package/clients/services/runner-service.js +0 -134
- package/clients/services/runner-service.ts +0 -225
package/clients/bus/bus.ts
DELETED
|
@@ -1,251 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Event Bus for pi-lens
|
|
3
|
-
*
|
|
4
|
-
* Decoupled pub/sub system for diagnostic events.
|
|
5
|
-
* Enables loose coupling between diagnostic producers (runners, LSP clients)
|
|
6
|
-
* and consumers (UI, aggregators, history trackers).
|
|
7
|
-
*/
|
|
8
|
-
|
|
9
|
-
import type { z } from "zod";
|
|
10
|
-
|
|
11
|
-
// --- Types ---
|
|
12
|
-
|
|
13
|
-
export interface BusEvent<T = unknown> {
|
|
14
|
-
type: string;
|
|
15
|
-
properties: T;
|
|
16
|
-
timestamp: number;
|
|
17
|
-
}
|
|
18
|
-
|
|
19
|
-
export type EventHandler<T> = (event: BusEvent<T>) => void | Promise<void>;
|
|
20
|
-
|
|
21
|
-
// --- Internal State ---
|
|
22
|
-
|
|
23
|
-
const subscribers = new Map<string, Set<EventHandler<unknown>>>();
|
|
24
|
-
const globalMiddleware: Array<(event: BusEvent) => BusEvent | undefined> = [];
|
|
25
|
-
|
|
26
|
-
let eventCount = 0;
|
|
27
|
-
let isDebugEnabled = false;
|
|
28
|
-
|
|
29
|
-
// --- Core Functions ---
|
|
30
|
-
|
|
31
|
-
function debug(type: string, event: BusEvent) {
|
|
32
|
-
if (!isDebugEnabled) return;
|
|
33
|
-
const timestamp = new Date(event.timestamp).toISOString();
|
|
34
|
-
console.error(`[bus] [${timestamp}] ${type}: ${event.type}`);
|
|
35
|
-
}
|
|
36
|
-
|
|
37
|
-
/**
|
|
38
|
-
* Publish an event to all subscribers
|
|
39
|
-
*/
|
|
40
|
-
export function publish<T>(event: BusEvent<T>): void {
|
|
41
|
-
eventCount++;
|
|
42
|
-
debug("publish", event as BusEvent<unknown>);
|
|
43
|
-
|
|
44
|
-
// Run through middleware
|
|
45
|
-
let currentEvent: BusEvent | undefined = event as BusEvent;
|
|
46
|
-
for (const mw of globalMiddleware) {
|
|
47
|
-
currentEvent = mw(currentEvent);
|
|
48
|
-
if (!currentEvent) return; // Middleware cancelled the event
|
|
49
|
-
}
|
|
50
|
-
|
|
51
|
-
const handlers = subscribers.get(event.type);
|
|
52
|
-
if (!handlers || handlers.size === 0) return;
|
|
53
|
-
|
|
54
|
-
// Notify all subscribers (fire-and-forget for async handlers)
|
|
55
|
-
for (const handler of handlers) {
|
|
56
|
-
try {
|
|
57
|
-
const result = handler(currentEvent as BusEvent<unknown>);
|
|
58
|
-
if (result instanceof Promise) {
|
|
59
|
-
result.catch((err) => {
|
|
60
|
-
console.error(`[bus] async handler error for ${event.type}:`, err);
|
|
61
|
-
});
|
|
62
|
-
}
|
|
63
|
-
} catch (err) {
|
|
64
|
-
console.error(`[bus] handler error for ${event.type}:`, err);
|
|
65
|
-
}
|
|
66
|
-
}
|
|
67
|
-
}
|
|
68
|
-
|
|
69
|
-
/**
|
|
70
|
-
* Subscribe to a specific event type
|
|
71
|
-
* @returns Unsubscribe function
|
|
72
|
-
*/
|
|
73
|
-
export function subscribe<T>(
|
|
74
|
-
eventType: string,
|
|
75
|
-
handler: EventHandler<T>,
|
|
76
|
-
): () => void {
|
|
77
|
-
if (!subscribers.has(eventType)) {
|
|
78
|
-
subscribers.set(eventType, new Set());
|
|
79
|
-
}
|
|
80
|
-
|
|
81
|
-
const handlers = subscribers.get(eventType)!;
|
|
82
|
-
handlers.add(handler as EventHandler<unknown>);
|
|
83
|
-
|
|
84
|
-
debug("subscribe", { type: eventType, properties: {}, timestamp: Date.now() });
|
|
85
|
-
|
|
86
|
-
// Return unsubscribe function
|
|
87
|
-
return () => {
|
|
88
|
-
handlers.delete(handler as EventHandler<unknown>);
|
|
89
|
-
if (handlers.size === 0) {
|
|
90
|
-
subscribers.delete(eventType);
|
|
91
|
-
}
|
|
92
|
-
};
|
|
93
|
-
}
|
|
94
|
-
|
|
95
|
-
/**
|
|
96
|
-
* Subscribe to an event type and automatically unsubscribe after first match
|
|
97
|
-
*/
|
|
98
|
-
export function once<T>(
|
|
99
|
-
eventType: string,
|
|
100
|
-
predicate?: (event: BusEvent<T>) => boolean,
|
|
101
|
-
): Promise<BusEvent<T>> {
|
|
102
|
-
return new Promise((resolve) => {
|
|
103
|
-
const unsubscribe = subscribe<T>(eventType, (event) => {
|
|
104
|
-
if (!predicate || predicate(event)) {
|
|
105
|
-
unsubscribe();
|
|
106
|
-
resolve(event);
|
|
107
|
-
}
|
|
108
|
-
});
|
|
109
|
-
});
|
|
110
|
-
}
|
|
111
|
-
|
|
112
|
-
/**
|
|
113
|
-
* Wait for an event with timeout
|
|
114
|
-
*/
|
|
115
|
-
export function waitFor<T>(
|
|
116
|
-
eventType: string,
|
|
117
|
-
timeoutMs: number,
|
|
118
|
-
predicate?: (event: BusEvent<T>) => boolean,
|
|
119
|
-
): Promise<BusEvent<T> | undefined> {
|
|
120
|
-
return new Promise((resolve) => {
|
|
121
|
-
const timer = setTimeout(() => {
|
|
122
|
-
unsubscribe();
|
|
123
|
-
resolve(undefined);
|
|
124
|
-
}, timeoutMs);
|
|
125
|
-
|
|
126
|
-
const unsubscribe = subscribe<T>(eventType, (event) => {
|
|
127
|
-
if (!predicate || predicate(event)) {
|
|
128
|
-
clearTimeout(timer);
|
|
129
|
-
unsubscribe();
|
|
130
|
-
resolve(event);
|
|
131
|
-
}
|
|
132
|
-
});
|
|
133
|
-
});
|
|
134
|
-
}
|
|
135
|
-
|
|
136
|
-
// --- Middleware ---
|
|
137
|
-
|
|
138
|
-
export function addMiddleware(
|
|
139
|
-
mw: (event: BusEvent) => BusEvent | undefined,
|
|
140
|
-
): () => void {
|
|
141
|
-
globalMiddleware.push(mw);
|
|
142
|
-
return () => {
|
|
143
|
-
const idx = globalMiddleware.indexOf(mw);
|
|
144
|
-
if (idx !== -1) globalMiddleware.splice(idx, 1);
|
|
145
|
-
};
|
|
146
|
-
}
|
|
147
|
-
|
|
148
|
-
// --- Utilities ---
|
|
149
|
-
|
|
150
|
-
export function enableDebug(enabled = true): void {
|
|
151
|
-
isDebugEnabled = enabled;
|
|
152
|
-
}
|
|
153
|
-
|
|
154
|
-
export function getStats(): {
|
|
155
|
-
subscriberCount: number;
|
|
156
|
-
eventTypes: string[];
|
|
157
|
-
totalEvents: number;
|
|
158
|
-
} {
|
|
159
|
-
return {
|
|
160
|
-
subscriberCount: Array.from(subscribers.values()).reduce(
|
|
161
|
-
(sum, set) => sum + set.size,
|
|
162
|
-
0,
|
|
163
|
-
),
|
|
164
|
-
eventTypes: Array.from(subscribers.keys()),
|
|
165
|
-
totalEvents: eventCount,
|
|
166
|
-
};
|
|
167
|
-
}
|
|
168
|
-
|
|
169
|
-
export function clearAllSubscribers(): void {
|
|
170
|
-
subscribers.clear();
|
|
171
|
-
}
|
|
172
|
-
|
|
173
|
-
// --- Event Factory ---
|
|
174
|
-
|
|
175
|
-
export interface EventDefinition<T> {
|
|
176
|
-
type: string;
|
|
177
|
-
create(properties: T): BusEvent<T>;
|
|
178
|
-
subscribe(handler: EventHandler<T>): () => void;
|
|
179
|
-
publish(properties: T): void;
|
|
180
|
-
}
|
|
181
|
-
|
|
182
|
-
export namespace BusEvent {
|
|
183
|
-
/**
|
|
184
|
-
* Define a typed event type with Zod schema validation
|
|
185
|
-
*/
|
|
186
|
-
export function define<T>(
|
|
187
|
-
type: string,
|
|
188
|
-
_schema: z.ZodType<T>,
|
|
189
|
-
): EventDefinition<T> {
|
|
190
|
-
return {
|
|
191
|
-
type,
|
|
192
|
-
create(properties): BusEvent<T> {
|
|
193
|
-
return {
|
|
194
|
-
type,
|
|
195
|
-
properties,
|
|
196
|
-
timestamp: Date.now(),
|
|
197
|
-
};
|
|
198
|
-
},
|
|
199
|
-
subscribe(handler: EventHandler<T>): () => void {
|
|
200
|
-
return subscribe(type, handler);
|
|
201
|
-
},
|
|
202
|
-
publish(properties: T): void {
|
|
203
|
-
publish({
|
|
204
|
-
type,
|
|
205
|
-
properties,
|
|
206
|
-
timestamp: Date.now(),
|
|
207
|
-
});
|
|
208
|
-
},
|
|
209
|
-
};
|
|
210
|
-
}
|
|
211
|
-
|
|
212
|
-
/**
|
|
213
|
-
* Create a simple event type without schema (for internal use)
|
|
214
|
-
*/
|
|
215
|
-
export function defineSimple<T>(type: string): EventDefinition<T> {
|
|
216
|
-
return {
|
|
217
|
-
type,
|
|
218
|
-
create(properties: T): BusEvent<T> {
|
|
219
|
-
return {
|
|
220
|
-
type,
|
|
221
|
-
properties,
|
|
222
|
-
timestamp: Date.now(),
|
|
223
|
-
};
|
|
224
|
-
},
|
|
225
|
-
subscribe(handler: EventHandler<T>): () => void {
|
|
226
|
-
return subscribe(type, handler);
|
|
227
|
-
},
|
|
228
|
-
publish(properties: T): void {
|
|
229
|
-
publish({
|
|
230
|
-
type,
|
|
231
|
-
properties,
|
|
232
|
-
timestamp: Date.now(),
|
|
233
|
-
});
|
|
234
|
-
},
|
|
235
|
-
};
|
|
236
|
-
}
|
|
237
|
-
|
|
238
|
-
/**
|
|
239
|
-
* Create a raw event (helper)
|
|
240
|
-
*/
|
|
241
|
-
export function create<T>(type: string, properties: T): BusEvent<T> {
|
|
242
|
-
return {
|
|
243
|
-
type,
|
|
244
|
-
properties,
|
|
245
|
-
timestamp: Date.now(),
|
|
246
|
-
};
|
|
247
|
-
}
|
|
248
|
-
}
|
|
249
|
-
|
|
250
|
-
// --- Re-export for convenience ---
|
|
251
|
-
export { subscribe as on, publish as emit };
|
package/clients/bus/events.js
DELETED
|
@@ -1,214 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Diagnostic Event Types for pi-lens
|
|
3
|
-
*
|
|
4
|
-
* Standardized events for the bus system.
|
|
5
|
-
* These events flow through the system:
|
|
6
|
-
* - Runners publish DiagnosticFound events
|
|
7
|
-
* - LSP clients publish LspDiagnostic events
|
|
8
|
-
* - Aggregators subscribe and build reports
|
|
9
|
-
* - UI subscribes for real-time display
|
|
10
|
-
*/
|
|
11
|
-
import { z } from "zod";
|
|
12
|
-
import { BusEvent } from "./bus.js";
|
|
13
|
-
// --- Shared Schemas ---
|
|
14
|
-
export const DiagnosticSeverity = z.enum(["error", "warning", "info", "hint"]);
|
|
15
|
-
export const OutputSemantic = z.enum([
|
|
16
|
-
"blocking", // Hard stop - must fix
|
|
17
|
-
"warning", // Soft stop - should fix
|
|
18
|
-
"fixed", // Auto-fix applied
|
|
19
|
-
"silent", // Track but don't display
|
|
20
|
-
"none", // No action needed
|
|
21
|
-
]);
|
|
22
|
-
export const DiagnosticSchema = z.object({
|
|
23
|
-
id: z.string(), // Unique for deduplication
|
|
24
|
-
message: z.string(),
|
|
25
|
-
filePath: z.string(),
|
|
26
|
-
line: z.number().optional(),
|
|
27
|
-
column: z.number().optional(),
|
|
28
|
-
severity: DiagnosticSeverity,
|
|
29
|
-
semantic: OutputSemantic,
|
|
30
|
-
tool: z.string(), // Which tool produced this
|
|
31
|
-
rule: z.string().optional(),
|
|
32
|
-
fixable: z.boolean().optional(),
|
|
33
|
-
fixSuggestion: z.string().optional(),
|
|
34
|
-
});
|
|
35
|
-
export const RunnerStatus = z.enum([
|
|
36
|
-
"starting",
|
|
37
|
-
"running",
|
|
38
|
-
"completed",
|
|
39
|
-
"failed",
|
|
40
|
-
"skipped",
|
|
41
|
-
]);
|
|
42
|
-
// --- Event Definitions ---
|
|
43
|
-
/**
|
|
44
|
-
* Fired when a runner discovers diagnostics
|
|
45
|
-
* Published by: dispatch runners
|
|
46
|
-
* Subscribed by: aggregators, delta tracker, UI
|
|
47
|
-
*/
|
|
48
|
-
export const DiagnosticFound = BusEvent.define("diagnostic.found", z.object({
|
|
49
|
-
runnerId: z.string(),
|
|
50
|
-
filePath: z.string(),
|
|
51
|
-
diagnostics: z.array(DiagnosticSchema),
|
|
52
|
-
durationMs: z.number(),
|
|
53
|
-
}));
|
|
54
|
-
/**
|
|
55
|
-
* Fired when a file is modified
|
|
56
|
-
* Published by: tool_result handler, file watcher
|
|
57
|
-
* Subscribed by: runner scheduler, cache invalidator
|
|
58
|
-
*/
|
|
59
|
-
export const FileModified = BusEvent.define("file.modified", z.object({
|
|
60
|
-
filePath: z.string(),
|
|
61
|
-
content: z.string().optional(),
|
|
62
|
-
changeType: z.enum(["write", "edit", "external"]),
|
|
63
|
-
}));
|
|
64
|
-
/**
|
|
65
|
-
* Fired when a file is created
|
|
66
|
-
* Published by: file watcher
|
|
67
|
-
* Subscribed by: runner scheduler
|
|
68
|
-
*/
|
|
69
|
-
export const FileCreated = BusEvent.define("file.created", z.object({
|
|
70
|
-
filePath: z.string(),
|
|
71
|
-
}));
|
|
72
|
-
/**
|
|
73
|
-
* Fired when a file is deleted
|
|
74
|
-
* Published by: file watcher
|
|
75
|
-
* Subscribed by: cache invalidator
|
|
76
|
-
*/
|
|
77
|
-
export const FileDeleted = BusEvent.define("file.deleted", z.object({
|
|
78
|
-
filePath: z.string(),
|
|
79
|
-
}));
|
|
80
|
-
/**
|
|
81
|
-
* Fired when a runner starts execution
|
|
82
|
-
* Published by: dispatcher
|
|
83
|
-
* Subscribed by: progress UI, metrics
|
|
84
|
-
*/
|
|
85
|
-
export const RunnerStarted = BusEvent.define("runner.started", z.object({
|
|
86
|
-
runnerId: z.string(),
|
|
87
|
-
filePath: z.string(),
|
|
88
|
-
timestamp: z.number(),
|
|
89
|
-
}));
|
|
90
|
-
/**
|
|
91
|
-
* Fired when a runner completes
|
|
92
|
-
* Published by: dispatcher
|
|
93
|
-
* Subscribed by: progress UI, metrics aggregator
|
|
94
|
-
*/
|
|
95
|
-
export const RunnerCompleted = BusEvent.define("runner.completed", z.object({
|
|
96
|
-
runnerId: z.string(),
|
|
97
|
-
filePath: z.string(),
|
|
98
|
-
status: RunnerStatus,
|
|
99
|
-
durationMs: z.number(),
|
|
100
|
-
diagnosticCount: z.number(),
|
|
101
|
-
}));
|
|
102
|
-
/**
|
|
103
|
-
* Fired when LSP publishes diagnostics
|
|
104
|
-
* Published by: LSPClient (via textDocument/publishDiagnostics)
|
|
105
|
-
* Subscribed by: diagnostic aggregator
|
|
106
|
-
*/
|
|
107
|
-
export const LspDiagnostic = BusEvent.define("lsp.diagnostic", z.object({
|
|
108
|
-
serverId: z.string(), // e.g., "typescript", "pyright"
|
|
109
|
-
filePath: z.string(),
|
|
110
|
-
diagnostics: z.array(z.object({
|
|
111
|
-
severity: z.number(), // 1=error, 2=warn, 3=info, 4=hint
|
|
112
|
-
message: z.string(),
|
|
113
|
-
range: z.object({
|
|
114
|
-
start: z.object({ line: z.number(), character: z.number() }),
|
|
115
|
-
end: z.object({ line: z.number(), character: z.number() }),
|
|
116
|
-
}),
|
|
117
|
-
code: z.union([z.string(), z.number()]).optional(),
|
|
118
|
-
source: z.string().optional(),
|
|
119
|
-
})),
|
|
120
|
-
version: z.number().optional(), // Document version for debouncing
|
|
121
|
-
}));
|
|
122
|
-
/**
|
|
123
|
-
* Fired when baseline is updated (for delta mode)
|
|
124
|
-
* Published by: delta tracker
|
|
125
|
-
* Subscribed by: diagnostic filter
|
|
126
|
-
*/
|
|
127
|
-
export const BaselineUpdated = BusEvent.define("baseline.updated", z.object({
|
|
128
|
-
filePath: z.string(),
|
|
129
|
-
diagnosticIds: z.array(z.string()),
|
|
130
|
-
timestamp: z.number(),
|
|
131
|
-
}));
|
|
132
|
-
/**
|
|
133
|
-
* Fired when aggregated report is ready
|
|
134
|
-
* Published by: report aggregator
|
|
135
|
-
* Subscribed by: UI, commands
|
|
136
|
-
*/
|
|
137
|
-
export const ReportReady = BusEvent.define("report.ready", z.object({
|
|
138
|
-
filePath: z.string(),
|
|
139
|
-
report: z.object({
|
|
140
|
-
blockers: z.array(DiagnosticSchema),
|
|
141
|
-
warnings: z.array(DiagnosticSchema),
|
|
142
|
-
fixed: z.array(DiagnosticSchema),
|
|
143
|
-
silent: z.array(DiagnosticSchema),
|
|
144
|
-
}),
|
|
145
|
-
durationMs: z.number(),
|
|
146
|
-
}));
|
|
147
|
-
/**
|
|
148
|
-
* Fired when auto-fix is applied
|
|
149
|
-
* Published by: autofix runner
|
|
150
|
-
* Subscribed by: UI, file watcher
|
|
151
|
-
*/
|
|
152
|
-
export const AutoFixApplied = BusEvent.define("autofix.applied", z.object({
|
|
153
|
-
filePath: z.string(),
|
|
154
|
-
runnerId: z.string(),
|
|
155
|
-
fixesApplied: z.number(),
|
|
156
|
-
fixes: z.array(z.object({
|
|
157
|
-
line: z.number(),
|
|
158
|
-
message: z.string(),
|
|
159
|
-
})),
|
|
160
|
-
}));
|
|
161
|
-
/**
|
|
162
|
-
* Fired when session starts
|
|
163
|
-
* Published by: session_start handler
|
|
164
|
-
* Subscribed by: cache manager, file watcher
|
|
165
|
-
*/
|
|
166
|
-
export const SessionStarted = BusEvent.define("session.started", z.object({
|
|
167
|
-
cwd: z.string(),
|
|
168
|
-
timestamp: z.number(),
|
|
169
|
-
}));
|
|
170
|
-
/**
|
|
171
|
-
* Fired when turn ends
|
|
172
|
-
* Published by: turn_end handler
|
|
173
|
-
* Subscribed by: batch processor, metrics
|
|
174
|
-
*/
|
|
175
|
-
export const TurnEnded = BusEvent.define("turn.ended", z.object({
|
|
176
|
-
cwd: z.string(),
|
|
177
|
-
modifiedFiles: z.array(z.string()),
|
|
178
|
-
timestamp: z.number(),
|
|
179
|
-
}));
|
|
180
|
-
// --- Event Aggregator Helper ---
|
|
181
|
-
export class DiagnosticAggregator {
|
|
182
|
-
constructor() {
|
|
183
|
-
this.diagnostics = new Map();
|
|
184
|
-
this.unsubscribe = null;
|
|
185
|
-
}
|
|
186
|
-
start() {
|
|
187
|
-
this.unsubscribe = DiagnosticFound.subscribe((event) => {
|
|
188
|
-
const { filePath, diagnostics } = event.properties;
|
|
189
|
-
const existing = this.diagnostics.get(filePath) ?? [];
|
|
190
|
-
// Merge and dedupe by id
|
|
191
|
-
const merged = [...existing, ...diagnostics];
|
|
192
|
-
const unique = new Map(merged.map(d => [d.id, d]));
|
|
193
|
-
this.diagnostics.set(filePath, Array.from(unique.values()));
|
|
194
|
-
});
|
|
195
|
-
}
|
|
196
|
-
stop() {
|
|
197
|
-
this.unsubscribe?.();
|
|
198
|
-
this.unsubscribe = null;
|
|
199
|
-
}
|
|
200
|
-
getForFile(filePath) {
|
|
201
|
-
return this.diagnostics.get(filePath) ?? [];
|
|
202
|
-
}
|
|
203
|
-
getAll() {
|
|
204
|
-
return new Map(this.diagnostics);
|
|
205
|
-
}
|
|
206
|
-
clear(filePath) {
|
|
207
|
-
if (filePath) {
|
|
208
|
-
this.diagnostics.delete(filePath);
|
|
209
|
-
}
|
|
210
|
-
else {
|
|
211
|
-
this.diagnostics.clear();
|
|
212
|
-
}
|
|
213
|
-
}
|
|
214
|
-
}
|