pi-lens 2.2.9 → 3.0.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/CHANGELOG.md +198 -0
- package/README.md +709 -519
- package/clients/__tests__/file-time.test.js +216 -0
- package/clients/__tests__/file-time.test.ts +276 -0
- package/clients/__tests__/format-service.test.js +245 -0
- package/clients/__tests__/format-service.test.ts +339 -0
- package/clients/__tests__/formatters.test.js +271 -0
- package/clients/__tests__/formatters.test.ts +401 -0
- package/clients/amain-types.js +164 -0
- package/clients/amain-types.ts +165 -0
- package/clients/architect-client.js +56 -12
- package/clients/architect-client.ts +81 -16
- package/clients/ast-grep-client.js +2 -2
- package/clients/ast-grep-client.ts +14 -39
- package/clients/ast-grep-parser.ts +1 -1
- package/clients/ast-grep-rule-manager.js +8 -0
- package/clients/ast-grep-rule-manager.ts +10 -1
- package/clients/ast-grep-types.js +9 -0
- package/clients/ast-grep-types.ts +106 -0
- package/clients/auto-loop.js +10 -0
- package/clients/auto-loop.ts +14 -1
- package/clients/biome-client.js +81 -19
- package/clients/biome-client.ts +103 -22
- package/clients/bus/bus.js +191 -0
- package/clients/bus/bus.ts +251 -0
- package/clients/bus/events.js +214 -0
- package/clients/bus/events.ts +279 -0
- package/clients/bus/index.js +8 -0
- package/clients/bus/index.ts +9 -0
- package/clients/bus/integration.js +158 -0
- package/clients/bus/integration.ts +214 -0
- package/clients/complexity-client.js +13 -7
- package/clients/complexity-client.ts +13 -7
- package/clients/config-validator.js +465 -0
- package/clients/config-validator.ts +558 -0
- package/clients/dependency-checker.js +4 -10
- package/clients/dependency-checker.ts +4 -10
- package/clients/dispatch/__tests__/autofix-integration.test.js +245 -0
- package/clients/dispatch/__tests__/autofix-integration.test.ts +300 -0
- package/clients/dispatch/__tests__/runner-registration.test.js +236 -0
- package/clients/dispatch/__tests__/runner-registration.test.ts +282 -0
- package/clients/dispatch/bus-dispatcher.js +177 -0
- package/clients/dispatch/bus-dispatcher.ts +251 -0
- package/clients/dispatch/dispatcher.edge.test.js +82 -0
- package/clients/dispatch/dispatcher.edge.test.ts +100 -0
- package/clients/dispatch/dispatcher.format.test.js +46 -0
- package/clients/dispatch/dispatcher.format.test.ts +58 -0
- package/clients/dispatch/dispatcher.inline.test.js +74 -0
- package/clients/dispatch/dispatcher.inline.test.ts +93 -0
- package/clients/dispatch/dispatcher.js +19 -53
- package/clients/dispatch/dispatcher.ts +20 -67
- package/clients/dispatch/plan.js +9 -4
- package/clients/dispatch/plan.ts +9 -4
- package/clients/dispatch/runners/architect.js +21 -7
- package/clients/dispatch/runners/architect.test.js +138 -0
- package/clients/dispatch/runners/architect.test.ts +162 -0
- package/clients/dispatch/runners/architect.ts +22 -7
- package/clients/dispatch/runners/ast-grep-napi.js +462 -0
- package/clients/dispatch/runners/ast-grep-napi.test.js +111 -0
- package/clients/dispatch/runners/ast-grep-napi.test.ts +133 -0
- package/clients/dispatch/runners/ast-grep-napi.ts +506 -0
- package/clients/dispatch/runners/ast-grep.js +62 -19
- package/clients/dispatch/runners/ast-grep.ts +70 -18
- package/clients/dispatch/runners/biome.js +29 -53
- package/clients/dispatch/runners/biome.ts +29 -63
- package/clients/dispatch/runners/config-validation.js +67 -0
- package/clients/dispatch/runners/config-validation.ts +82 -0
- package/clients/dispatch/runners/go-vet.js +4 -28
- package/clients/dispatch/runners/go-vet.ts +4 -32
- package/clients/dispatch/runners/index.js +30 -10
- package/clients/dispatch/runners/index.ts +30 -10
- package/clients/dispatch/runners/oxlint.js +141 -0
- package/clients/dispatch/runners/oxlint.test.js +230 -0
- package/clients/dispatch/runners/oxlint.test.ts +303 -0
- package/clients/dispatch/runners/oxlint.ts +175 -0
- package/clients/dispatch/runners/pyright.js +40 -70
- package/clients/dispatch/runners/pyright.test.js +16 -2
- package/clients/dispatch/runners/pyright.test.ts +14 -2
- package/clients/dispatch/runners/pyright.ts +48 -91
- package/clients/dispatch/runners/python-slop.js +97 -0
- package/clients/dispatch/runners/python-slop.test.js +203 -0
- package/clients/dispatch/runners/python-slop.test.ts +298 -0
- package/clients/dispatch/runners/python-slop.ts +124 -0
- package/clients/dispatch/runners/ruff.js +18 -71
- package/clients/dispatch/runners/ruff.ts +19 -79
- package/clients/dispatch/runners/rust-clippy.js +28 -32
- package/clients/dispatch/runners/rust-clippy.ts +29 -31
- package/clients/dispatch/runners/scan_codebase.test.js +89 -0
- package/clients/dispatch/runners/scan_codebase.test.ts +105 -0
- package/clients/dispatch/runners/shellcheck.js +147 -0
- package/clients/dispatch/runners/shellcheck.test.js +98 -0
- package/clients/dispatch/runners/shellcheck.test.ts +129 -0
- package/clients/dispatch/runners/shellcheck.ts +188 -0
- package/clients/dispatch/runners/similarity.js +230 -0
- package/clients/dispatch/runners/similarity.ts +339 -0
- package/clients/dispatch/runners/spellcheck.js +106 -0
- package/clients/dispatch/runners/spellcheck.test.js +158 -0
- package/clients/dispatch/runners/spellcheck.test.ts +214 -0
- package/clients/dispatch/runners/spellcheck.ts +136 -0
- package/clients/dispatch/runners/tree-sitter.js +107 -0
- package/clients/dispatch/runners/tree-sitter.ts +135 -0
- package/clients/dispatch/runners/ts-lsp.js +104 -33
- package/clients/dispatch/runners/ts-lsp.ts +120 -38
- package/clients/dispatch/runners/ts-slop.js +113 -0
- package/clients/dispatch/runners/ts-slop.test.js +180 -0
- package/clients/dispatch/runners/ts-slop.test.ts +230 -0
- package/clients/dispatch/runners/ts-slop.ts +142 -0
- package/clients/dispatch/runners/utils/diagnostic-parsers.js +134 -0
- package/clients/dispatch/runners/utils/diagnostic-parsers.ts +186 -0
- package/clients/dispatch/runners/utils/runner-helpers.js +115 -0
- package/clients/dispatch/runners/utils/runner-helpers.ts +167 -0
- package/clients/dispatch/runners/utils.js +2 -4
- package/clients/dispatch/runners/utils.ts +2 -4
- package/clients/dispatch/types.ts +1 -1
- package/clients/dispatch/utils/format-utils.js +49 -0
- package/clients/dispatch/utils/format-utils.ts +60 -0
- package/clients/dogfood.test.js +201 -0
- package/clients/dogfood.test.ts +269 -0
- package/clients/file-time.js +152 -0
- package/clients/file-time.ts +208 -0
- package/clients/file-utils.js +40 -0
- package/clients/file-utils.ts +44 -0
- package/clients/fix-scanners.js +10 -20
- package/clients/fix-scanners.ts +10 -22
- package/clients/format-service.js +172 -0
- package/clients/format-service.ts +254 -0
- package/clients/formatters.js +435 -0
- package/clients/formatters.ts +508 -0
- package/clients/go-client.js +5 -14
- package/clients/go-client.ts +5 -13
- package/clients/installer/index.js +356 -0
- package/clients/installer/index.ts +426 -0
- package/clients/jscpd-client.js +11 -9
- package/clients/jscpd-client.ts +12 -8
- package/clients/knip-client.js +3 -7
- package/clients/knip-client.ts +3 -6
- package/clients/lsp/__tests__/client.test.js +325 -0
- package/clients/lsp/__tests__/client.test.ts +434 -0
- package/clients/lsp/__tests__/config.test.js +166 -0
- package/clients/lsp/__tests__/config.test.ts +209 -0
- package/clients/lsp/__tests__/error-recovery.test.js +213 -0
- package/clients/lsp/__tests__/error-recovery.test.ts +279 -0
- package/clients/lsp/__tests__/integration.test.js +127 -0
- package/clients/lsp/__tests__/integration.test.ts +160 -0
- package/clients/lsp/__tests__/launch.test.js +260 -0
- package/clients/lsp/__tests__/launch.test.ts +329 -0
- package/clients/lsp/__tests__/server.test.js +259 -0
- package/clients/lsp/__tests__/server.test.ts +332 -0
- package/clients/lsp/__tests__/service.test.js +417 -0
- package/clients/lsp/__tests__/service.test.ts +499 -0
- package/clients/lsp/client.js +235 -0
- package/clients/lsp/client.ts +328 -0
- package/clients/lsp/config.js +115 -0
- package/clients/lsp/config.ts +149 -0
- package/clients/lsp/index.js +222 -0
- package/clients/lsp/index.ts +280 -0
- package/clients/lsp/installer/index.js +391 -0
- package/clients/lsp/interactive-install.js +210 -0
- package/clients/lsp/interactive-install.ts +251 -0
- package/clients/lsp/language.js +170 -0
- package/clients/lsp/language.ts +216 -0
- package/clients/lsp/launch.js +174 -0
- package/clients/lsp/launch.ts +240 -0
- package/clients/lsp/lsp/launch.js +116 -0
- package/clients/lsp/lsp/server.js +532 -0
- package/clients/lsp/lsp-index.js +10 -0
- package/clients/lsp/lsp-index.ts +11 -0
- package/clients/lsp/path-utils.js +48 -0
- package/clients/lsp/path-utils.ts +52 -0
- package/clients/lsp/server.js +615 -0
- package/clients/lsp/server.ts +800 -0
- package/clients/lsp/test-py-spawn/requirements.txt +1 -0
- package/clients/lsp/test-py-spawn/test.py +3 -0
- package/clients/lsp/test-py-svc/requirements.txt +1 -0
- package/clients/lsp/test-py-svc/test.py +3 -0
- package/clients/lsp/test-python-project/requirements.txt +1 -0
- package/clients/lsp/test-python-project/test.py +5 -0
- package/clients/metrics-history.js +2 -2
- package/clients/metrics-history.ts +2 -2
- package/clients/production-readiness.js +522 -0
- package/clients/production-readiness.ts +556 -0
- package/clients/project-index.js +255 -0
- package/clients/project-index.ts +383 -0
- package/clients/project-metadata.js +531 -0
- package/clients/project-metadata.ts +624 -0
- package/clients/ruff-client.js +56 -16
- package/clients/ruff-client.ts +72 -15
- package/clients/runner-tracker.js +152 -0
- package/clients/runner-tracker.ts +213 -0
- package/clients/rust-client.js +4 -11
- package/clients/rust-client.ts +5 -11
- package/clients/safe-spawn.js +96 -0
- package/clients/safe-spawn.ts +128 -0
- package/clients/scan-architectural-debt.js +3 -6
- package/clients/scan-architectural-debt.ts +3 -6
- package/clients/scan-utils.js +5 -20
- package/clients/scan-utils.ts +5 -29
- package/clients/secrets-scanner.js +3 -17
- package/clients/secrets-scanner.ts +4 -20
- package/clients/services/__tests__/effect-integration.test.js +86 -0
- package/clients/services/__tests__/effect-integration.test.ts +111 -0
- package/clients/services/effect-integration.js +194 -0
- package/clients/services/effect-integration.ts +268 -0
- package/clients/services/index.js +7 -0
- package/clients/services/index.ts +8 -0
- package/clients/services/runner-service.js +105 -0
- package/clients/services/runner-service.ts +179 -0
- package/clients/sg-runner.js +87 -13
- package/clients/sg-runner.ts +97 -13
- package/clients/state-matrix.js +160 -0
- package/clients/state-matrix.ts +202 -0
- package/clients/subprocess-client.js +10 -9
- package/clients/subprocess-client.ts +10 -8
- package/clients/test-runner-client.js +3 -7
- package/clients/test-runner-client.ts +3 -6
- package/clients/tool-availability.js +4 -10
- package/clients/tool-availability.ts +4 -9
- package/clients/tree-sitter-client.js +564 -0
- package/clients/tree-sitter-client.ts +797 -0
- package/clients/tree-sitter-query-loader.js +355 -0
- package/clients/tree-sitter-query-loader.ts +425 -0
- package/clients/type-coverage-client.js +3 -7
- package/clients/type-coverage-client.ts +3 -6
- package/clients/typescript-client.codefix.test.js +157 -0
- package/clients/typescript-client.codefix.test.ts +186 -0
- package/clients/typescript-client.js +43 -0
- package/clients/typescript-client.ts +98 -0
- package/commands/booboo.js +799 -219
- package/commands/booboo.ts +1004 -225
- package/commands/clients/ast-grep-client.js +250 -0
- package/commands/clients/ast-grep-parser.js +86 -0
- package/commands/clients/ast-grep-rule-manager.js +91 -0
- package/commands/clients/ast-grep-types.js +9 -0
- package/commands/clients/biome-client.js +380 -0
- package/commands/clients/complexity-client.js +667 -0
- package/commands/clients/file-kinds.js +177 -0
- package/commands/clients/file-utils.js +40 -0
- package/commands/clients/jscpd-client.js +169 -0
- package/commands/clients/knip-client.js +211 -0
- package/commands/clients/ruff-client.js +297 -0
- package/commands/clients/safe-spawn.js +88 -0
- package/commands/clients/scan-utils.js +83 -0
- package/commands/clients/sg-runner.js +190 -0
- package/commands/clients/types.js +11 -0
- package/commands/clients/typescript-client.js +505 -0
- package/commands/fix-from-booboo.js +398 -0
- package/commands/fix-from-booboo.ts +485 -0
- package/commands/fix-simplified.js +618 -0
- package/commands/fix-simplified.ts +768 -0
- package/commands/rate.js +10 -14
- package/commands/rate.ts +9 -16
- package/default-architect.yaml +59 -15
- package/index.ts +342 -429
- package/package.json +16 -3
- package/rules/ast-grep-rules/rules/empty-catch.yml +38 -13
- package/rules/ast-grep-rules/rules/no-array-constructor.yml +1 -0
- package/rules/ast-grep-rules/rules/no-debugger.yml +2 -0
- package/rules/python-slop-rules/.sgconfig.yml +4 -0
- package/rules/python-slop-rules/rules/slop-rules.yml +647 -0
- package/rules/tree-sitter-queries/python/bare-except.yml +54 -0
- package/rules/tree-sitter-queries/python/eval-exec.yml +50 -0
- package/rules/tree-sitter-queries/python/is-vs-equals.yml +60 -0
- package/rules/tree-sitter-queries/python/mutable-default-arg.yml +57 -0
- package/rules/tree-sitter-queries/python/unreachable-except.yml +60 -0
- package/rules/tree-sitter-queries/python/wildcard-import.yml +46 -0
- package/rules/tree-sitter-queries/tsx/dangerously-set-inner-html.yml +63 -0
- package/rules/tree-sitter-queries/typescript/await-in-loop.yml +56 -0
- package/rules/tree-sitter-queries/typescript/console-statement.yml +47 -0
- package/rules/tree-sitter-queries/typescript/debugger.yml +47 -0
- package/rules/tree-sitter-queries/typescript/deep-nesting.yml +117 -0
- package/rules/tree-sitter-queries/typescript/deep-promise-chain.yml +73 -0
- package/rules/tree-sitter-queries/typescript/empty-catch.yml +64 -0
- package/rules/tree-sitter-queries/typescript/eval.yml +48 -0
- package/rules/tree-sitter-queries/typescript/hardcoded-secrets.yml +78 -0
- package/rules/tree-sitter-queries/typescript/long-parameter-list.yml +62 -0
- package/rules/tree-sitter-queries/typescript/mixed-async-styles.yml +49 -0
- package/rules/tree-sitter-queries/typescript/nested-ternary.yml +45 -0
- package/rules/ts-slop-rules/.sgconfig.yml +4 -0
- package/rules/ts-slop-rules/rules/in-correct-optional-input-type.yml +10 -0
- package/rules/ts-slop-rules/rules/jwt-no-verify.yml +13 -0
- package/rules/ts-slop-rules/rules/no-architecture-violation.yml +10 -0
- package/rules/ts-slop-rules/rules/no-case-declarations.yml +10 -0
- package/rules/ts-slop-rules/rules/no-dangerously-set-inner-html.yml +10 -0
- package/rules/ts-slop-rules/rules/no-debugger.yml +10 -0
- package/rules/ts-slop-rules/rules/no-dupe-args.yml +10 -0
- package/rules/ts-slop-rules/rules/no-dupe-class-members.yml +10 -0
- package/rules/ts-slop-rules/rules/no-dupe-keys.yml +10 -0
- package/rules/ts-slop-rules/rules/no-eval.yml +13 -0
- package/rules/ts-slop-rules/rules/no-hardcoded-secrets.yml +12 -0
- package/rules/ts-slop-rules/rules/no-implied-eval.yml +12 -0
- package/rules/ts-slop-rules/rules/no-inner-html.yml +13 -0
- package/rules/ts-slop-rules/rules/no-javascript-url.yml +10 -0
- package/rules/ts-slop-rules/rules/no-mutable-default.yml +10 -0
- package/rules/ts-slop-rules/rules/no-nested-links.yml +12 -0
- package/rules/ts-slop-rules/rules/no-new-symbol.yml +10 -0
- package/rules/ts-slop-rules/rules/no-new-wrappers.yml +13 -0
- package/rules/ts-slop-rules/rules/no-open-redirect.yml +16 -0
- package/rules/ts-slop-rules/rules/slop-rules.yml +455 -0
- package/rules/ts-slop-rules/rules/weak-rsa-key.yml +12 -0
- package/skills/ast-grep/SKILL.md +182 -0
- package/clients/dispatch/runners/secrets.js +0 -109
- package/commands/fix.js +0 -244
- package/commands/fix.ts +0 -373
- package/rules/ast-grep-rules/rules/no-lonely-if.yml +0 -13
|
@@ -0,0 +1,214 @@
|
|
|
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
|
+
}
|
|
@@ -0,0 +1,279 @@
|
|
|
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
|
+
|
|
12
|
+
import { z } from "zod";
|
|
13
|
+
import { BusEvent } from "./bus.js";
|
|
14
|
+
|
|
15
|
+
// --- Shared Schemas ---
|
|
16
|
+
|
|
17
|
+
export const DiagnosticSeverity = z.enum(["error", "warning", "info", "hint"]);
|
|
18
|
+
export type DiagnosticSeverity = z.infer<typeof DiagnosticSeverity>;
|
|
19
|
+
|
|
20
|
+
export const OutputSemantic = z.enum([
|
|
21
|
+
"blocking", // Hard stop - must fix
|
|
22
|
+
"warning", // Soft stop - should fix
|
|
23
|
+
"fixed", // Auto-fix applied
|
|
24
|
+
"silent", // Track but don't display
|
|
25
|
+
"none", // No action needed
|
|
26
|
+
]);
|
|
27
|
+
export type OutputSemantic = z.infer<typeof OutputSemantic>;
|
|
28
|
+
|
|
29
|
+
export const DiagnosticSchema = z.object({
|
|
30
|
+
id: z.string(), // Unique for deduplication
|
|
31
|
+
message: z.string(),
|
|
32
|
+
filePath: z.string(),
|
|
33
|
+
line: z.number().optional(),
|
|
34
|
+
column: z.number().optional(),
|
|
35
|
+
severity: DiagnosticSeverity,
|
|
36
|
+
semantic: OutputSemantic,
|
|
37
|
+
tool: z.string(), // Which tool produced this
|
|
38
|
+
rule: z.string().optional(),
|
|
39
|
+
fixable: z.boolean().optional(),
|
|
40
|
+
fixSuggestion: z.string().optional(),
|
|
41
|
+
});
|
|
42
|
+
export type Diagnostic = z.infer<typeof DiagnosticSchema>;
|
|
43
|
+
|
|
44
|
+
export const RunnerStatus = z.enum([
|
|
45
|
+
"starting",
|
|
46
|
+
"running",
|
|
47
|
+
"completed",
|
|
48
|
+
"failed",
|
|
49
|
+
"skipped",
|
|
50
|
+
]);
|
|
51
|
+
export type RunnerStatus = z.infer<typeof RunnerStatus>;
|
|
52
|
+
|
|
53
|
+
// --- Event Definitions ---
|
|
54
|
+
|
|
55
|
+
/**
|
|
56
|
+
* Fired when a runner discovers diagnostics
|
|
57
|
+
* Published by: dispatch runners
|
|
58
|
+
* Subscribed by: aggregators, delta tracker, UI
|
|
59
|
+
*/
|
|
60
|
+
export const DiagnosticFound = BusEvent.define(
|
|
61
|
+
"diagnostic.found",
|
|
62
|
+
z.object({
|
|
63
|
+
runnerId: z.string(),
|
|
64
|
+
filePath: z.string(),
|
|
65
|
+
diagnostics: z.array(DiagnosticSchema),
|
|
66
|
+
durationMs: z.number(),
|
|
67
|
+
}),
|
|
68
|
+
);
|
|
69
|
+
|
|
70
|
+
/**
|
|
71
|
+
* Fired when a file is modified
|
|
72
|
+
* Published by: tool_result handler, file watcher
|
|
73
|
+
* Subscribed by: runner scheduler, cache invalidator
|
|
74
|
+
*/
|
|
75
|
+
export const FileModified = BusEvent.define(
|
|
76
|
+
"file.modified",
|
|
77
|
+
z.object({
|
|
78
|
+
filePath: z.string(),
|
|
79
|
+
content: z.string().optional(),
|
|
80
|
+
changeType: z.enum(["write", "edit", "external"]),
|
|
81
|
+
}),
|
|
82
|
+
);
|
|
83
|
+
|
|
84
|
+
/**
|
|
85
|
+
* Fired when a file is created
|
|
86
|
+
* Published by: file watcher
|
|
87
|
+
* Subscribed by: runner scheduler
|
|
88
|
+
*/
|
|
89
|
+
export const FileCreated = BusEvent.define(
|
|
90
|
+
"file.created",
|
|
91
|
+
z.object({
|
|
92
|
+
filePath: z.string(),
|
|
93
|
+
}),
|
|
94
|
+
);
|
|
95
|
+
|
|
96
|
+
/**
|
|
97
|
+
* Fired when a file is deleted
|
|
98
|
+
* Published by: file watcher
|
|
99
|
+
* Subscribed by: cache invalidator
|
|
100
|
+
*/
|
|
101
|
+
export const FileDeleted = BusEvent.define(
|
|
102
|
+
"file.deleted",
|
|
103
|
+
z.object({
|
|
104
|
+
filePath: z.string(),
|
|
105
|
+
}),
|
|
106
|
+
);
|
|
107
|
+
|
|
108
|
+
/**
|
|
109
|
+
* Fired when a runner starts execution
|
|
110
|
+
* Published by: dispatcher
|
|
111
|
+
* Subscribed by: progress UI, metrics
|
|
112
|
+
*/
|
|
113
|
+
export const RunnerStarted = BusEvent.define(
|
|
114
|
+
"runner.started",
|
|
115
|
+
z.object({
|
|
116
|
+
runnerId: z.string(),
|
|
117
|
+
filePath: z.string(),
|
|
118
|
+
timestamp: z.number(),
|
|
119
|
+
}),
|
|
120
|
+
);
|
|
121
|
+
|
|
122
|
+
/**
|
|
123
|
+
* Fired when a runner completes
|
|
124
|
+
* Published by: dispatcher
|
|
125
|
+
* Subscribed by: progress UI, metrics aggregator
|
|
126
|
+
*/
|
|
127
|
+
export const RunnerCompleted = BusEvent.define(
|
|
128
|
+
"runner.completed",
|
|
129
|
+
z.object({
|
|
130
|
+
runnerId: z.string(),
|
|
131
|
+
filePath: z.string(),
|
|
132
|
+
status: RunnerStatus,
|
|
133
|
+
durationMs: z.number(),
|
|
134
|
+
diagnosticCount: z.number(),
|
|
135
|
+
}),
|
|
136
|
+
);
|
|
137
|
+
|
|
138
|
+
/**
|
|
139
|
+
* Fired when LSP publishes diagnostics
|
|
140
|
+
* Published by: LSPClient (via textDocument/publishDiagnostics)
|
|
141
|
+
* Subscribed by: diagnostic aggregator
|
|
142
|
+
*/
|
|
143
|
+
export const LspDiagnostic = BusEvent.define(
|
|
144
|
+
"lsp.diagnostic",
|
|
145
|
+
z.object({
|
|
146
|
+
serverId: z.string(), // e.g., "typescript", "pyright"
|
|
147
|
+
filePath: z.string(),
|
|
148
|
+
diagnostics: z.array(z.object({
|
|
149
|
+
severity: z.number(), // 1=error, 2=warn, 3=info, 4=hint
|
|
150
|
+
message: z.string(),
|
|
151
|
+
range: z.object({
|
|
152
|
+
start: z.object({ line: z.number(), character: z.number() }),
|
|
153
|
+
end: z.object({ line: z.number(), character: z.number() }),
|
|
154
|
+
}),
|
|
155
|
+
code: z.union([z.string(), z.number()]).optional(),
|
|
156
|
+
source: z.string().optional(),
|
|
157
|
+
})),
|
|
158
|
+
version: z.number().optional(), // Document version for debouncing
|
|
159
|
+
}),
|
|
160
|
+
);
|
|
161
|
+
|
|
162
|
+
/**
|
|
163
|
+
* Fired when baseline is updated (for delta mode)
|
|
164
|
+
* Published by: delta tracker
|
|
165
|
+
* Subscribed by: diagnostic filter
|
|
166
|
+
*/
|
|
167
|
+
export const BaselineUpdated = BusEvent.define(
|
|
168
|
+
"baseline.updated",
|
|
169
|
+
z.object({
|
|
170
|
+
filePath: z.string(),
|
|
171
|
+
diagnosticIds: z.array(z.string()),
|
|
172
|
+
timestamp: z.number(),
|
|
173
|
+
}),
|
|
174
|
+
);
|
|
175
|
+
|
|
176
|
+
/**
|
|
177
|
+
* Fired when aggregated report is ready
|
|
178
|
+
* Published by: report aggregator
|
|
179
|
+
* Subscribed by: UI, commands
|
|
180
|
+
*/
|
|
181
|
+
export const ReportReady = BusEvent.define(
|
|
182
|
+
"report.ready",
|
|
183
|
+
z.object({
|
|
184
|
+
filePath: z.string(),
|
|
185
|
+
report: z.object({
|
|
186
|
+
blockers: z.array(DiagnosticSchema),
|
|
187
|
+
warnings: z.array(DiagnosticSchema),
|
|
188
|
+
fixed: z.array(DiagnosticSchema),
|
|
189
|
+
silent: z.array(DiagnosticSchema),
|
|
190
|
+
}),
|
|
191
|
+
durationMs: z.number(),
|
|
192
|
+
}),
|
|
193
|
+
);
|
|
194
|
+
|
|
195
|
+
/**
|
|
196
|
+
* Fired when auto-fix is applied
|
|
197
|
+
* Published by: autofix runner
|
|
198
|
+
* Subscribed by: UI, file watcher
|
|
199
|
+
*/
|
|
200
|
+
export const AutoFixApplied = BusEvent.define(
|
|
201
|
+
"autofix.applied",
|
|
202
|
+
z.object({
|
|
203
|
+
filePath: z.string(),
|
|
204
|
+
runnerId: z.string(),
|
|
205
|
+
fixesApplied: z.number(),
|
|
206
|
+
fixes: z.array(z.object({
|
|
207
|
+
line: z.number(),
|
|
208
|
+
message: z.string(),
|
|
209
|
+
})),
|
|
210
|
+
}),
|
|
211
|
+
);
|
|
212
|
+
|
|
213
|
+
/**
|
|
214
|
+
* Fired when session starts
|
|
215
|
+
* Published by: session_start handler
|
|
216
|
+
* Subscribed by: cache manager, file watcher
|
|
217
|
+
*/
|
|
218
|
+
export const SessionStarted = BusEvent.define(
|
|
219
|
+
"session.started",
|
|
220
|
+
z.object({
|
|
221
|
+
cwd: z.string(),
|
|
222
|
+
timestamp: z.number(),
|
|
223
|
+
}),
|
|
224
|
+
);
|
|
225
|
+
|
|
226
|
+
/**
|
|
227
|
+
* Fired when turn ends
|
|
228
|
+
* Published by: turn_end handler
|
|
229
|
+
* Subscribed by: batch processor, metrics
|
|
230
|
+
*/
|
|
231
|
+
export const TurnEnded = BusEvent.define(
|
|
232
|
+
"turn.ended",
|
|
233
|
+
z.object({
|
|
234
|
+
cwd: z.string(),
|
|
235
|
+
modifiedFiles: z.array(z.string()),
|
|
236
|
+
timestamp: z.number(),
|
|
237
|
+
}),
|
|
238
|
+
);
|
|
239
|
+
|
|
240
|
+
// --- Event Aggregator Helper ---
|
|
241
|
+
|
|
242
|
+
export class DiagnosticAggregator {
|
|
243
|
+
private diagnostics = new Map<string, Diagnostic[]>();
|
|
244
|
+
private unsubscribe: (() => void) | null = null;
|
|
245
|
+
|
|
246
|
+
start() {
|
|
247
|
+
this.unsubscribe = DiagnosticFound.subscribe((event) => {
|
|
248
|
+
const { filePath, diagnostics } = event.properties;
|
|
249
|
+
const existing = this.diagnostics.get(filePath) ?? [];
|
|
250
|
+
|
|
251
|
+
// Merge and dedupe by id
|
|
252
|
+
const merged = [...existing, ...diagnostics];
|
|
253
|
+
const unique = new Map(merged.map(d => [d.id, d]));
|
|
254
|
+
|
|
255
|
+
this.diagnostics.set(filePath, Array.from(unique.values()));
|
|
256
|
+
});
|
|
257
|
+
}
|
|
258
|
+
|
|
259
|
+
stop() {
|
|
260
|
+
this.unsubscribe?.();
|
|
261
|
+
this.unsubscribe = null;
|
|
262
|
+
}
|
|
263
|
+
|
|
264
|
+
getForFile(filePath: string): Diagnostic[] {
|
|
265
|
+
return this.diagnostics.get(filePath) ?? [];
|
|
266
|
+
}
|
|
267
|
+
|
|
268
|
+
getAll(): Map<string, Diagnostic[]> {
|
|
269
|
+
return new Map(this.diagnostics);
|
|
270
|
+
}
|
|
271
|
+
|
|
272
|
+
clear(filePath?: string) {
|
|
273
|
+
if (filePath) {
|
|
274
|
+
this.diagnostics.delete(filePath);
|
|
275
|
+
} else {
|
|
276
|
+
this.diagnostics.clear();
|
|
277
|
+
}
|
|
278
|
+
}
|
|
279
|
+
}
|
|
@@ -0,0 +1,158 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Bus Integration for pi-lens
|
|
3
|
+
*
|
|
4
|
+
* Connects the event bus system to the existing pi-lens architecture.
|
|
5
|
+
* This provides:
|
|
6
|
+
* - Event aggregation for diagnostic collection
|
|
7
|
+
* - Real-time progress tracking
|
|
8
|
+
* - Hook integration for tool_result handler
|
|
9
|
+
*/
|
|
10
|
+
import { RunnerStarted, RunnerCompleted, ReportReady, FileModified, DiagnosticAggregator, } from "./events.js";
|
|
11
|
+
import { enableDebug } from "./bus.js";
|
|
12
|
+
const state = {
|
|
13
|
+
aggregator: new DiagnosticAggregator(),
|
|
14
|
+
runnerInProgress: new Set(),
|
|
15
|
+
lastReport: new Map(),
|
|
16
|
+
isEnabled: false,
|
|
17
|
+
};
|
|
18
|
+
// --- Event Subscribers ---
|
|
19
|
+
let unsubscribers = [];
|
|
20
|
+
/**
|
|
21
|
+
* Initialize the bus integration
|
|
22
|
+
* Call this from session_start handler
|
|
23
|
+
*/
|
|
24
|
+
export function initBusIntegration(pi, options) {
|
|
25
|
+
if (state.isEnabled)
|
|
26
|
+
return; // Already initialized
|
|
27
|
+
if (options?.debug) {
|
|
28
|
+
enableDebug(true);
|
|
29
|
+
}
|
|
30
|
+
// Start the diagnostic aggregator
|
|
31
|
+
state.aggregator.start();
|
|
32
|
+
// Subscribe to runner progress events for UI feedback
|
|
33
|
+
const unsubRunnerStarted = RunnerStarted.subscribe((event) => {
|
|
34
|
+
const { runnerId, filePath } = event.properties;
|
|
35
|
+
state.runnerInProgress.add(`${runnerId}:${filePath}`);
|
|
36
|
+
});
|
|
37
|
+
const unsubRunnerCompleted = RunnerCompleted.subscribe((event) => {
|
|
38
|
+
const { runnerId, filePath, durationMs, diagnosticCount } = event.properties;
|
|
39
|
+
state.runnerInProgress.delete(`${runnerId}:${filePath}`);
|
|
40
|
+
// Log slow runners in debug mode
|
|
41
|
+
if (options?.debug && durationMs > 5000) {
|
|
42
|
+
console.error(`[bus] Slow runner: ${runnerId} took ${durationMs}ms for ${filePath}`);
|
|
43
|
+
}
|
|
44
|
+
// Log runners that found issues
|
|
45
|
+
if (diagnosticCount > 0) {
|
|
46
|
+
console.error(`[bus] ${runnerId} found ${diagnosticCount} issues in ${filePath}`);
|
|
47
|
+
}
|
|
48
|
+
});
|
|
49
|
+
// Cache reports for quick retrieval
|
|
50
|
+
const unsubReportReady = ReportReady.subscribe((event) => {
|
|
51
|
+
const { filePath, report, durationMs } = event.properties;
|
|
52
|
+
// Store the report
|
|
53
|
+
state.lastReport.set(filePath, {
|
|
54
|
+
output: formatReport(report, durationMs),
|
|
55
|
+
timestamp: Date.now(),
|
|
56
|
+
});
|
|
57
|
+
});
|
|
58
|
+
// Track file modifications to clear stale data
|
|
59
|
+
const unsubFileModified = FileModified.subscribe((event) => {
|
|
60
|
+
const { filePath } = event.properties;
|
|
61
|
+
// Clear cached report for modified file
|
|
62
|
+
state.lastReport.delete(filePath);
|
|
63
|
+
// Clear diagnostics aggregator for this file (will be repopulated)
|
|
64
|
+
state.aggregator.clear(filePath);
|
|
65
|
+
});
|
|
66
|
+
// Store unsubscribers for cleanup
|
|
67
|
+
unsubscribers = [
|
|
68
|
+
unsubRunnerStarted,
|
|
69
|
+
unsubRunnerCompleted,
|
|
70
|
+
unsubReportReady,
|
|
71
|
+
unsubFileModified,
|
|
72
|
+
];
|
|
73
|
+
state.isEnabled = true;
|
|
74
|
+
console.error("[pi-lens] Bus integration initialized");
|
|
75
|
+
}
|
|
76
|
+
/**
|
|
77
|
+
* Shutdown the bus integration
|
|
78
|
+
* Call this when the extension is disabled
|
|
79
|
+
*/
|
|
80
|
+
export function shutdownBusIntegration() {
|
|
81
|
+
if (!state.isEnabled)
|
|
82
|
+
return;
|
|
83
|
+
// Stop all subscribers
|
|
84
|
+
for (const unsub of unsubscribers) {
|
|
85
|
+
unsub();
|
|
86
|
+
}
|
|
87
|
+
unsubscribers = [];
|
|
88
|
+
// Stop the aggregator
|
|
89
|
+
state.aggregator.stop();
|
|
90
|
+
// Clear all state
|
|
91
|
+
state.runnerInProgress.clear();
|
|
92
|
+
state.lastReport.clear();
|
|
93
|
+
state.aggregator.clear();
|
|
94
|
+
state.isEnabled = false;
|
|
95
|
+
}
|
|
96
|
+
// --- Helper Functions ---
|
|
97
|
+
function formatReport(report, durationMs) {
|
|
98
|
+
const lines = [];
|
|
99
|
+
if (report.blockers.length > 0) {
|
|
100
|
+
lines.push(`🔴 STOP — ${report.blockers.length} issue(s) must be fixed:`);
|
|
101
|
+
for (const d of report.blockers.slice(0, 5)) {
|
|
102
|
+
const line = d.line ? `L${d.line}: ` : "";
|
|
103
|
+
lines.push(` ${line}${d.message.split("\n")[0]}`);
|
|
104
|
+
}
|
|
105
|
+
if (report.blockers.length > 5) {
|
|
106
|
+
lines.push(` ... and ${report.blockers.length - 5} more`);
|
|
107
|
+
}
|
|
108
|
+
}
|
|
109
|
+
if (report.fixed.length > 0) {
|
|
110
|
+
lines.push(`✅ Auto-fixed ${report.fixed.length} issue(s)`);
|
|
111
|
+
}
|
|
112
|
+
if (lines.length > 0) {
|
|
113
|
+
lines.push(`(completed in ${durationMs}ms)`);
|
|
114
|
+
}
|
|
115
|
+
return lines.join("\n");
|
|
116
|
+
}
|
|
117
|
+
// --- API for index.ts ---
|
|
118
|
+
/**
|
|
119
|
+
* Get aggregated diagnostics for a file
|
|
120
|
+
*/
|
|
121
|
+
export function getDiagnosticsForFile(filePath) {
|
|
122
|
+
return state.aggregator.getForFile(filePath);
|
|
123
|
+
}
|
|
124
|
+
/**
|
|
125
|
+
* Get the last report output for a file
|
|
126
|
+
*/
|
|
127
|
+
export function getLastReport(filePath) {
|
|
128
|
+
return state.lastReport.get(filePath)?.output;
|
|
129
|
+
}
|
|
130
|
+
/**
|
|
131
|
+
* Check if any runners are currently in progress for a file
|
|
132
|
+
*/
|
|
133
|
+
export function hasRunnersInProgress(filePath) {
|
|
134
|
+
if (filePath) {
|
|
135
|
+
for (const key of state.runnerInProgress) {
|
|
136
|
+
if (key.endsWith(`:${filePath}`))
|
|
137
|
+
return true;
|
|
138
|
+
}
|
|
139
|
+
return false;
|
|
140
|
+
}
|
|
141
|
+
return state.runnerInProgress.size > 0;
|
|
142
|
+
}
|
|
143
|
+
/**
|
|
144
|
+
* Get list of runners in progress
|
|
145
|
+
*/
|
|
146
|
+
export function getRunnersInProgress() {
|
|
147
|
+
return Array.from(state.runnerInProgress).map((key) => {
|
|
148
|
+
const [runnerId, filePath] = key.split(":");
|
|
149
|
+
return { runnerId, filePath };
|
|
150
|
+
});
|
|
151
|
+
}
|
|
152
|
+
/**
|
|
153
|
+
* Clear all cached data
|
|
154
|
+
*/
|
|
155
|
+
export function clearBusCache() {
|
|
156
|
+
state.lastReport.clear();
|
|
157
|
+
state.aggregator.clear();
|
|
158
|
+
}
|