@alint-js/core 0.0.29 → 0.0.30
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/dist/{retry-C4sGjSE5.mjs → agent-weXkvGkc.mjs} +20 -1
- package/dist/agent.d.mts +3 -2
- package/dist/agent.mjs +2 -15
- package/dist/index.d.mts +55 -84
- package/dist/index.mjs +433 -530
- package/dist/structured-output.d.mts +1 -1
- package/dist/structured-output.mjs +5 -4
- package/dist/{types-CMLoj9J9.d.mts → types-CR_Grd6q.d.mts} +0 -1
- package/package.json +2 -2
package/dist/index.mjs
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { o as withAgentRetry, t as combineAbortSignals } from "./agent-weXkvGkc.mjs";
|
|
2
2
|
import { a as sliceRange, i as sliceLines, n as createSourceFile, r as createSourceRuntime, t as extractJsSourceTargets } from "./extract-CIWssxNK.mjs";
|
|
3
3
|
import { minimatch } from "minimatch";
|
|
4
4
|
import { isAbsolute, relative, resolve } from "pathe";
|
|
@@ -6,10 +6,10 @@ import { mkdir, readFile, rename, writeFile } from "node:fs/promises";
|
|
|
6
6
|
import { dirname, extname, isAbsolute as isAbsolute$1, join, relative as relative$1, resolve as resolve$1, sep } from "node:path";
|
|
7
7
|
import { AsyncLocalStorage } from "node:async_hooks";
|
|
8
8
|
import process, { cwd } from "node:process";
|
|
9
|
-
import { errorCauseFrom, errorMessageFrom } from "@moeru/std/error";
|
|
10
9
|
import { createHash, randomUUID } from "node:crypto";
|
|
11
10
|
import { statSync } from "node:fs";
|
|
12
11
|
import { array, check, description, is, literal, number, object, optional, pipe, record, string, union, unknown } from "valibot";
|
|
12
|
+
import { errorMessageFrom } from "@moeru/std/error";
|
|
13
13
|
//#region src/config/config-array.ts
|
|
14
14
|
const effectiveBasePathSymbol = Symbol("effectiveBasePath");
|
|
15
15
|
const inheritedMatcherScopesSymbol = Symbol("inheritedMatcherScopes");
|
|
@@ -580,99 +580,177 @@ function statSyncIsDirectory(path) {
|
|
|
580
580
|
return statSync(path).isDirectory();
|
|
581
581
|
}
|
|
582
582
|
//#endregion
|
|
583
|
-
//#region src/core/targets/directory.ts
|
|
584
|
-
function createDirectoryExecutionPlans(directories, fileOffset) {
|
|
585
|
-
return directories.map((directory, directoryOffset) => {
|
|
586
|
-
const executions = directory.ruleRuntimes.map((runtime) => {
|
|
587
|
-
if (runtime.handlers.onTargetWith) return {
|
|
588
|
-
run: () => runtime.handlers.onTargetWith?.(directory.target),
|
|
589
|
-
runtime
|
|
590
|
-
};
|
|
591
|
-
if (runtime.handlers.onTargetDirectory) return {
|
|
592
|
-
run: () => runtime.handlers.onTargetDirectory?.(directory.target),
|
|
593
|
-
runtime
|
|
594
|
-
};
|
|
595
|
-
}).filter((execution) => execution !== void 0);
|
|
596
|
-
const targets = executions.length === 0 ? [] : [{
|
|
597
|
-
activeFilePath: directory.target.path,
|
|
598
|
-
cacheFilePaths: [],
|
|
599
|
-
configHash: directory.configHash,
|
|
600
|
-
executions,
|
|
601
|
-
identity: directory.target.path,
|
|
602
|
-
kind: "directory",
|
|
603
|
-
language: "directory",
|
|
604
|
-
text: directory.target.path
|
|
605
|
-
}];
|
|
606
|
-
return {
|
|
607
|
-
emitFileProgress: true,
|
|
608
|
-
fileIndex: fileOffset + directoryOffset + 1,
|
|
609
|
-
path: directory.target.path,
|
|
610
|
-
planned: executions.length,
|
|
611
|
-
targets
|
|
612
|
-
};
|
|
613
|
-
});
|
|
614
|
-
}
|
|
615
|
-
//#endregion
|
|
616
583
|
//#region package.json
|
|
617
|
-
var version = "0.0.
|
|
584
|
+
var version = "0.0.30";
|
|
618
585
|
//#endregion
|
|
619
|
-
//#region src/core/
|
|
620
|
-
var
|
|
621
|
-
|
|
622
|
-
constructor(
|
|
623
|
-
|
|
624
|
-
super(message, { cause: error });
|
|
625
|
-
this.name = "AlintRuleExecutionError";
|
|
626
|
-
this.failure = {
|
|
627
|
-
filePath: path.file.path,
|
|
628
|
-
message,
|
|
629
|
-
ruleId: path.rule.id,
|
|
630
|
-
target: {
|
|
631
|
-
kind: path.target.kind,
|
|
632
|
-
name: path.target.name
|
|
633
|
-
}
|
|
634
|
-
};
|
|
586
|
+
//#region src/core/execution/job.ts
|
|
587
|
+
var CacheReplayProcessingError = class {
|
|
588
|
+
cause;
|
|
589
|
+
constructor(cause) {
|
|
590
|
+
this.cause = cause;
|
|
635
591
|
}
|
|
636
592
|
};
|
|
637
|
-
|
|
638
|
-
|
|
593
|
+
function createRuleJobs(plans) {
|
|
594
|
+
const jobs = [];
|
|
595
|
+
const total = plans.reduce((sum, plan) => sum + plan.planned, 0);
|
|
596
|
+
for (const plan of plans) for (const target of plan.targets) for (const execution of target.executions) {
|
|
597
|
+
const ruleId = execution.runtime.enabledRule.id;
|
|
598
|
+
const index = jobs.length + 1;
|
|
599
|
+
jobs.push({
|
|
600
|
+
execution,
|
|
601
|
+
job: {
|
|
602
|
+
id: stableHash({
|
|
603
|
+
index,
|
|
604
|
+
planId: plan.id,
|
|
605
|
+
ruleId,
|
|
606
|
+
targetIdentity: target.identity
|
|
607
|
+
}),
|
|
608
|
+
index,
|
|
609
|
+
inputPath: plan.path,
|
|
610
|
+
ruleId,
|
|
611
|
+
target: {
|
|
612
|
+
identity: target.identity,
|
|
613
|
+
kind: target.kind,
|
|
614
|
+
name: target.name
|
|
615
|
+
},
|
|
616
|
+
total
|
|
617
|
+
},
|
|
618
|
+
target
|
|
619
|
+
});
|
|
620
|
+
}
|
|
621
|
+
return jobs;
|
|
639
622
|
}
|
|
640
|
-
function
|
|
641
|
-
|
|
642
|
-
|
|
643
|
-
|
|
644
|
-
|
|
645
|
-
|
|
646
|
-
|
|
647
|
-
|
|
648
|
-
|
|
649
|
-
|
|
650
|
-
|
|
651
|
-
|
|
623
|
+
async function executeRuleJob(job, options) {
|
|
624
|
+
const bucket = {
|
|
625
|
+
diagnostics: [],
|
|
626
|
+
usage: []
|
|
627
|
+
};
|
|
628
|
+
if (options.runSignal?.aborted) return finish(job, options, bucket, {
|
|
629
|
+
cache: "miss",
|
|
630
|
+
state: "cancelled"
|
|
631
|
+
});
|
|
632
|
+
const cacheKey = createExecutionCacheKey(job, options.cache);
|
|
633
|
+
const cachedEntry = cacheKey ? options.cache.store.get(cacheKey) : void 0;
|
|
634
|
+
if (cacheKey && cachedEntry) {
|
|
635
|
+
rememberCacheEntry(options.cache, job.target.cacheFilePaths, cacheKey);
|
|
636
|
+
try {
|
|
637
|
+
replayCachedEntry(cachedEntry, bucket, job.job, options.progress);
|
|
638
|
+
} catch (error) {
|
|
639
|
+
if (!(error instanceof CacheReplayProcessingError)) throw error;
|
|
640
|
+
return finish(job, options, bucket, {
|
|
641
|
+
cache: "hit",
|
|
642
|
+
cause: error.cause,
|
|
643
|
+
failure: failure(error.cause, job, "cache-replay"),
|
|
644
|
+
state: "failed"
|
|
645
|
+
});
|
|
646
|
+
}
|
|
647
|
+
return finish(job, options, bucket, {
|
|
648
|
+
cache: "hit",
|
|
649
|
+
state: "cached"
|
|
650
|
+
});
|
|
651
|
+
}
|
|
652
|
+
if (options.cacheOnly) return finish(job, options, bucket, {
|
|
653
|
+
cache: "miss",
|
|
654
|
+
state: "skipped"
|
|
655
|
+
});
|
|
656
|
+
const controller = new AbortController();
|
|
657
|
+
let timedOut = false;
|
|
658
|
+
let deadlineError;
|
|
659
|
+
const forwardRunAbort = () => controller.abort(options.runSignal?.reason);
|
|
660
|
+
if (options.runSignal?.aborted) forwardRunAbort();
|
|
661
|
+
else options.runSignal?.addEventListener("abort", forwardRunAbort, { once: true });
|
|
662
|
+
const timer = options.timeoutMs == null ? void 0 : setTimeout(() => {
|
|
663
|
+
timedOut = true;
|
|
664
|
+
deadlineError = /* @__PURE__ */ new Error(`Rule execution timed out after ${options.timeoutMs}ms.`);
|
|
665
|
+
controller.abort(deadlineError);
|
|
666
|
+
}, options.timeoutMs);
|
|
667
|
+
const state = {
|
|
668
|
+
activeFilePath: job.target.activeFilePath,
|
|
669
|
+
bucket,
|
|
670
|
+
job: job.job,
|
|
671
|
+
reporterFailed: false,
|
|
672
|
+
signal: controller.signal
|
|
673
|
+
};
|
|
674
|
+
let handlerCause;
|
|
675
|
+
let handlerFailed = false;
|
|
676
|
+
try {
|
|
677
|
+
await job.execution.runtime.executionState.run(state, job.execution.run);
|
|
678
|
+
} catch (cause) {
|
|
679
|
+
if (state.reporterFailed) throw state.reporterCause;
|
|
680
|
+
handlerCause = cause;
|
|
681
|
+
handlerFailed = true;
|
|
682
|
+
} finally {
|
|
683
|
+
if (timer != null) clearTimeout(timer);
|
|
684
|
+
options.runSignal?.removeEventListener("abort", forwardRunAbort);
|
|
685
|
+
}
|
|
686
|
+
if (state.reporterFailed) throw state.reporterCause;
|
|
687
|
+
if (!timedOut && !handlerFailed && cacheKey) try {
|
|
688
|
+
options.cache.store.set(cacheKey, createCacheEntry(job, options.cache, bucket));
|
|
689
|
+
rememberCacheEntry(options.cache, job.target.cacheFilePaths, cacheKey);
|
|
690
|
+
} catch {}
|
|
691
|
+
if (options.runSignal?.aborted) return finish(job, options, bucket, {
|
|
692
|
+
cache: "miss",
|
|
693
|
+
state: "cancelled"
|
|
694
|
+
});
|
|
695
|
+
if (timedOut) return finish(job, options, bucket, {
|
|
696
|
+
cache: "miss",
|
|
697
|
+
cause: deadlineError,
|
|
698
|
+
failure: failure(deadlineError, job, "timeout"),
|
|
699
|
+
state: "failed"
|
|
700
|
+
});
|
|
701
|
+
if (handlerFailed) return finish(job, options, bucket, {
|
|
702
|
+
cache: "miss",
|
|
703
|
+
cause: handlerCause,
|
|
704
|
+
failure: failure(handlerCause, job, "handler"),
|
|
705
|
+
state: "failed"
|
|
706
|
+
});
|
|
707
|
+
return finish(job, options, bucket, {
|
|
708
|
+
cache: "miss",
|
|
709
|
+
state: "completed"
|
|
652
710
|
});
|
|
653
711
|
}
|
|
654
|
-
function
|
|
712
|
+
function resolveRuleExecutionTimeout(timeoutMs) {
|
|
713
|
+
if (timeoutMs === void 0) return void 0;
|
|
714
|
+
if (!Number.isFinite(timeoutMs) || !Number.isInteger(timeoutMs) || timeoutMs <= 0) throw new TypeError("Rule execution timeout must be a finite positive integer.");
|
|
715
|
+
return timeoutMs;
|
|
716
|
+
}
|
|
717
|
+
function createCacheEntry(job, cache, bucket) {
|
|
655
718
|
return {
|
|
656
|
-
|
|
657
|
-
|
|
658
|
-
|
|
659
|
-
|
|
660
|
-
|
|
661
|
-
|
|
662
|
-
|
|
663
|
-
id: ruleId,
|
|
664
|
-
index: entry.ruleIndex,
|
|
665
|
-
total: entry.ruleTotal
|
|
719
|
+
diagnostics: bucket.diagnostics,
|
|
720
|
+
filePath: normalizeCachePath(cache.cwd, job.job.inputPath),
|
|
721
|
+
fingerprint: {
|
|
722
|
+
alintVersion: version,
|
|
723
|
+
configHash: job.target.configHash,
|
|
724
|
+
modelHash: cache.modelHash,
|
|
725
|
+
ruleHash: job.execution.runtime.ruleHash
|
|
666
726
|
},
|
|
667
727
|
target: {
|
|
668
|
-
|
|
669
|
-
|
|
670
|
-
|
|
671
|
-
|
|
672
|
-
|
|
728
|
+
hash: createTargetHash(job),
|
|
729
|
+
identity: job.target.identity,
|
|
730
|
+
kind: job.target.kind,
|
|
731
|
+
loc: job.target.loc,
|
|
732
|
+
name: job.target.name,
|
|
733
|
+
range: job.target.range
|
|
734
|
+
},
|
|
735
|
+
usage: bucket.usage
|
|
673
736
|
};
|
|
674
737
|
}
|
|
675
|
-
function
|
|
738
|
+
function createExecutionCacheKey(job, cache) {
|
|
739
|
+
if (!cache.enabled || !job.execution.runtime.cacheable || job.target.cacheFilePaths.length === 0) return void 0;
|
|
740
|
+
return createCacheKey({
|
|
741
|
+
alintVersion: version,
|
|
742
|
+
configHash: job.target.configHash,
|
|
743
|
+
filePath: normalizeCachePath(cache.cwd, job.job.inputPath),
|
|
744
|
+
modelHash: cache.modelHash,
|
|
745
|
+
ruleHash: job.execution.runtime.ruleHash,
|
|
746
|
+
schemaVersion: 1,
|
|
747
|
+
targetHash: createTargetHash(job),
|
|
748
|
+
targetIdentity: job.target.identity,
|
|
749
|
+
targetKind: job.target.kind
|
|
750
|
+
});
|
|
751
|
+
}
|
|
752
|
+
function createTargetHash(job) {
|
|
753
|
+
const target = job.target;
|
|
676
754
|
return stableHash({
|
|
677
755
|
language: target.language,
|
|
678
756
|
loc: target.loc,
|
|
@@ -683,191 +761,28 @@ function createTargetHash(target) {
|
|
|
683
761
|
text: target.text
|
|
684
762
|
});
|
|
685
763
|
}
|
|
686
|
-
function
|
|
687
|
-
|
|
688
|
-
|
|
689
|
-
|
|
690
|
-
|
|
691
|
-
|
|
692
|
-
startedAt,
|
|
693
|
-
state: "errored"
|
|
694
|
-
});
|
|
695
|
-
} catch {}
|
|
696
|
-
}
|
|
697
|
-
async function executeRule(execution, path, target, options) {
|
|
698
|
-
const { cache, clock, counters, diagnostics, progress, signal, usage } = options;
|
|
699
|
-
signal?.throwIfAborted();
|
|
700
|
-
const startedAt = clock();
|
|
701
|
-
const cacheKey = createExecutionCacheKey(execution.runtime, target, path, cache);
|
|
702
|
-
const cachedEntry = cacheKey ? cache.store.get(cacheKey) : void 0;
|
|
703
|
-
progress?.onRuleStart?.({
|
|
704
|
-
path,
|
|
705
|
-
startedAt
|
|
706
|
-
});
|
|
707
|
-
if (cacheKey && cachedEntry) {
|
|
708
|
-
rememberCacheEntry(cache, target.cacheFilePaths, cacheKey);
|
|
709
|
-
try {
|
|
710
|
-
replayCachedEntry(cachedEntry, path, diagnostics, usage, progress);
|
|
711
|
-
} catch (error) {
|
|
712
|
-
counters.error();
|
|
713
|
-
emitErroredRuleEnd(progress, clock, path, startedAt, "hit");
|
|
714
|
-
throw new AlintRuleExecutionError(error, path);
|
|
715
|
-
}
|
|
716
|
-
counters.cache();
|
|
717
|
-
progress?.onRuleEnd?.({
|
|
718
|
-
cache: "hit",
|
|
719
|
-
endedAt: clock(),
|
|
720
|
-
path,
|
|
721
|
-
startedAt,
|
|
722
|
-
state: "completed"
|
|
723
|
-
});
|
|
724
|
-
return;
|
|
725
|
-
}
|
|
726
|
-
if (options.cacheOnly) {
|
|
727
|
-
counters.skip();
|
|
728
|
-
progress?.onRuleEnd?.({
|
|
729
|
-
cache: "miss",
|
|
730
|
-
endedAt: clock(),
|
|
731
|
-
path,
|
|
732
|
-
startedAt,
|
|
733
|
-
state: "skipped"
|
|
734
|
-
});
|
|
735
|
-
return;
|
|
736
|
-
}
|
|
737
|
-
let handlerError;
|
|
738
|
-
let handlerFailed = false;
|
|
739
|
-
const cacheDiagnostics = cacheKey ? [] : void 0;
|
|
740
|
-
const cacheUsage = cacheKey ? [] : void 0;
|
|
741
|
-
try {
|
|
742
|
-
await execution.runtime.executionState.run({
|
|
743
|
-
activeFilePath: target.activeFilePath,
|
|
744
|
-
cacheDiagnostics,
|
|
745
|
-
cacheUsage,
|
|
746
|
-
progressPath: path
|
|
747
|
-
}, execution.run);
|
|
748
|
-
} catch (error) {
|
|
749
|
-
handlerError = error;
|
|
750
|
-
handlerFailed = true;
|
|
751
|
-
}
|
|
752
|
-
if (handlerFailed) {
|
|
753
|
-
signal?.throwIfAborted();
|
|
754
|
-
counters.error();
|
|
755
|
-
emitErroredRuleEnd(progress, clock, path, startedAt, "miss");
|
|
756
|
-
throw new AlintRuleExecutionError(handlerError, path);
|
|
757
|
-
}
|
|
758
|
-
if (cacheKey) {
|
|
759
|
-
cache.store.set(cacheKey, {
|
|
760
|
-
diagnostics: cacheDiagnostics ?? [],
|
|
761
|
-
filePath: normalizeCachePath(cache.cwd, path.file.path),
|
|
762
|
-
fingerprint: {
|
|
763
|
-
alintVersion: version,
|
|
764
|
-
configHash: target.configHash,
|
|
765
|
-
modelHash: cache.modelHash,
|
|
766
|
-
ruleHash: execution.runtime.ruleHash
|
|
767
|
-
},
|
|
768
|
-
target: {
|
|
769
|
-
hash: createTargetHash(target),
|
|
770
|
-
identity: target.identity,
|
|
771
|
-
kind: target.kind,
|
|
772
|
-
loc: target.loc,
|
|
773
|
-
name: target.name,
|
|
774
|
-
range: target.range
|
|
775
|
-
},
|
|
776
|
-
usage: cacheUsage ?? []
|
|
777
|
-
});
|
|
778
|
-
rememberCacheEntry(cache, target.cacheFilePaths, cacheKey);
|
|
779
|
-
}
|
|
780
|
-
counters.complete();
|
|
781
|
-
progress?.onRuleEnd?.({
|
|
782
|
-
cache: "miss",
|
|
783
|
-
endedAt: clock(),
|
|
784
|
-
path,
|
|
785
|
-
startedAt,
|
|
786
|
-
state: "completed"
|
|
787
|
-
});
|
|
764
|
+
function failure(cause, job, kind) {
|
|
765
|
+
return {
|
|
766
|
+
job: job.job,
|
|
767
|
+
kind,
|
|
768
|
+
message: errorMessageFrom(cause) ?? String(cause)
|
|
769
|
+
};
|
|
788
770
|
}
|
|
789
|
-
|
|
790
|
-
const
|
|
791
|
-
|
|
792
|
-
|
|
793
|
-
|
|
794
|
-
path: plan.path,
|
|
795
|
-
planned: plan.planned,
|
|
796
|
-
total: filesTotal
|
|
771
|
+
function finish(job, options, bucket, terminal) {
|
|
772
|
+
const outcome = {
|
|
773
|
+
bucket,
|
|
774
|
+
job,
|
|
775
|
+
...terminal
|
|
797
776
|
};
|
|
798
|
-
|
|
799
|
-
|
|
800
|
-
|
|
777
|
+
options.progress?.onJobEnd?.({
|
|
778
|
+
cache: outcome.cache,
|
|
779
|
+
endedAt: options.clock(),
|
|
780
|
+
failure: outcome.failure,
|
|
781
|
+
job: job.job,
|
|
782
|
+
startedAt: options.startedAt,
|
|
783
|
+
state: outcome.state
|
|
801
784
|
});
|
|
802
|
-
|
|
803
|
-
let planFailed = false;
|
|
804
|
-
try {
|
|
805
|
-
for (const [targetOffset, target] of plan.targets.entries()) {
|
|
806
|
-
const targetPath = createProgressPath(plan.path, target.executions[0]?.runtime.enabledRule.id ?? "", {
|
|
807
|
-
fileIndex: plan.fileIndex,
|
|
808
|
-
filePlanned: plan.planned,
|
|
809
|
-
fileTotal: filesTotal,
|
|
810
|
-
ruleIndex: 1,
|
|
811
|
-
ruleTotal: target.executions.length,
|
|
812
|
-
targetIndex: targetOffset + 1,
|
|
813
|
-
targetKind: target.kind,
|
|
814
|
-
targetName: target.name,
|
|
815
|
-
targetTotal: plan.targets.length
|
|
816
|
-
});
|
|
817
|
-
const targetStartedAt = clock();
|
|
818
|
-
progress?.onTargetStart?.({
|
|
819
|
-
path: targetPath,
|
|
820
|
-
startedAt: targetStartedAt
|
|
821
|
-
});
|
|
822
|
-
let targetError;
|
|
823
|
-
let targetFailed = false;
|
|
824
|
-
try {
|
|
825
|
-
for (const [executionOffset, execution] of target.executions.entries()) await executeRule(execution, createProgressPath(plan.path, execution.runtime.enabledRule.id, {
|
|
826
|
-
fileIndex: plan.fileIndex,
|
|
827
|
-
filePlanned: plan.planned,
|
|
828
|
-
fileTotal: filesTotal,
|
|
829
|
-
ruleIndex: executionOffset + 1,
|
|
830
|
-
ruleTotal: target.executions.length,
|
|
831
|
-
targetIndex: targetOffset + 1,
|
|
832
|
-
targetKind: target.kind,
|
|
833
|
-
targetName: target.name,
|
|
834
|
-
targetTotal: plan.targets.length
|
|
835
|
-
}), target, options);
|
|
836
|
-
} catch (error) {
|
|
837
|
-
targetError = error;
|
|
838
|
-
targetFailed = true;
|
|
839
|
-
}
|
|
840
|
-
try {
|
|
841
|
-
progress?.onTargetEnd?.({
|
|
842
|
-
endedAt: clock(),
|
|
843
|
-
path: targetPath,
|
|
844
|
-
startedAt: targetStartedAt
|
|
845
|
-
});
|
|
846
|
-
} catch (error) {
|
|
847
|
-
if (!targetFailed) {
|
|
848
|
-
targetError = error;
|
|
849
|
-
targetFailed = true;
|
|
850
|
-
}
|
|
851
|
-
}
|
|
852
|
-
if (targetFailed) throw targetError;
|
|
853
|
-
}
|
|
854
|
-
} catch (error) {
|
|
855
|
-
planError = error;
|
|
856
|
-
planFailed = true;
|
|
857
|
-
}
|
|
858
|
-
if (plan.emitFileProgress) try {
|
|
859
|
-
progress?.onFileEnd?.({
|
|
860
|
-
endedAt: clock(),
|
|
861
|
-
file: fileProgress,
|
|
862
|
-
startedAt: fileStartedAt
|
|
863
|
-
});
|
|
864
|
-
} catch (error) {
|
|
865
|
-
if (!planFailed) {
|
|
866
|
-
planError = error;
|
|
867
|
-
planFailed = true;
|
|
868
|
-
}
|
|
869
|
-
}
|
|
870
|
-
if (planFailed) throw planError;
|
|
785
|
+
return outcome;
|
|
871
786
|
}
|
|
872
787
|
function rememberCacheEntry(cache, filePaths, cacheKey) {
|
|
873
788
|
for (const filePath of filePaths) {
|
|
@@ -877,29 +792,69 @@ function rememberCacheEntry(cache, filePaths, cacheKey) {
|
|
|
877
792
|
cache.fileEntryKeys.set(normalizedPath, entries);
|
|
878
793
|
}
|
|
879
794
|
}
|
|
880
|
-
function replayCachedEntry(entry,
|
|
881
|
-
|
|
795
|
+
function replayCachedEntry(entry, bucket, job, progress) {
|
|
796
|
+
let diagnostics;
|
|
797
|
+
let usage;
|
|
798
|
+
try {
|
|
799
|
+
diagnostics = entry.diagnostics;
|
|
800
|
+
usage = entry.usage;
|
|
801
|
+
} catch (cause) {
|
|
802
|
+
throw new CacheReplayProcessingError(cause);
|
|
803
|
+
}
|
|
804
|
+
for (const cachedDiagnostic of diagnostics) {
|
|
882
805
|
const diagnostic = {
|
|
883
806
|
...cachedDiagnostic,
|
|
884
807
|
cached: true
|
|
885
808
|
};
|
|
886
|
-
diagnostics.push(diagnostic);
|
|
809
|
+
bucket.diagnostics.push(diagnostic);
|
|
887
810
|
progress?.onDiagnostic?.({
|
|
888
811
|
diagnostic,
|
|
889
|
-
|
|
890
|
-
path
|
|
812
|
+
job
|
|
891
813
|
});
|
|
892
814
|
}
|
|
893
|
-
for (const
|
|
894
|
-
|
|
815
|
+
for (const record of usage) {
|
|
816
|
+
bucket.usage.push(record);
|
|
895
817
|
progress?.onUsage?.({
|
|
896
|
-
|
|
897
|
-
record
|
|
898
|
-
total: usage.toJSON()
|
|
818
|
+
job,
|
|
819
|
+
record
|
|
899
820
|
});
|
|
900
821
|
}
|
|
901
822
|
}
|
|
902
823
|
//#endregion
|
|
824
|
+
//#region src/core/targets/directory.ts
|
|
825
|
+
function createDirectoryExecutionPlans(directories, sourcePlanCount) {
|
|
826
|
+
return directories.map((directory, directoryOffset) => {
|
|
827
|
+
const executions = directory.ruleRuntimes.map((runtime) => {
|
|
828
|
+
if (runtime.handlers.onTargetWith) return {
|
|
829
|
+
run: () => runtime.handlers.onTargetWith?.(directory.target),
|
|
830
|
+
runtime
|
|
831
|
+
};
|
|
832
|
+
if (runtime.handlers.onTargetDirectory) return {
|
|
833
|
+
run: () => runtime.handlers.onTargetDirectory?.(directory.target),
|
|
834
|
+
runtime
|
|
835
|
+
};
|
|
836
|
+
}).filter((execution) => execution !== void 0);
|
|
837
|
+
const targets = executions.length === 0 ? [] : [{
|
|
838
|
+
activeFilePath: directory.target.path,
|
|
839
|
+
cacheFilePaths: [],
|
|
840
|
+
configHash: directory.configHash,
|
|
841
|
+
executions,
|
|
842
|
+
identity: directory.target.path,
|
|
843
|
+
kind: "directory",
|
|
844
|
+
language: "directory",
|
|
845
|
+
text: directory.target.path
|
|
846
|
+
}];
|
|
847
|
+
return {
|
|
848
|
+
id: `directory:${directory.target.path}`,
|
|
849
|
+
index: sourcePlanCount + directoryOffset + 1,
|
|
850
|
+
kind: "directory",
|
|
851
|
+
path: directory.target.path,
|
|
852
|
+
planned: executions.length,
|
|
853
|
+
targets
|
|
854
|
+
};
|
|
855
|
+
});
|
|
856
|
+
}
|
|
857
|
+
//#endregion
|
|
903
858
|
//#region src/core/targets/project.ts
|
|
904
859
|
function createProjectExecutionPlan(options) {
|
|
905
860
|
const project = createProjectTarget(options.root, options.files);
|
|
@@ -943,8 +898,9 @@ function createProjectExecutionPlan(options) {
|
|
|
943
898
|
})
|
|
944
899
|
};
|
|
945
900
|
return {
|
|
946
|
-
|
|
947
|
-
|
|
901
|
+
id: `project:${options.root}`,
|
|
902
|
+
index: options.index,
|
|
903
|
+
kind: "project",
|
|
948
904
|
path: options.root,
|
|
949
905
|
planned: executions.length,
|
|
950
906
|
targets: [target]
|
|
@@ -979,8 +935,9 @@ function createSourceExecutionPlans(files, cwd) {
|
|
|
979
935
|
const resolveTargetIdentity = createTargetIdentityResolver(targets.map((target) => toTargetIdentityInput(cwd, preparedFile.file.path, target)));
|
|
980
936
|
for (const target of targets) target.identity = resolveTargetIdentity(toTargetIdentityInput(cwd, preparedFile.file.path, target));
|
|
981
937
|
const filePlan = {
|
|
982
|
-
|
|
983
|
-
|
|
938
|
+
id: `source:${preparedFile.file.path}`,
|
|
939
|
+
index: fileOffset + 1,
|
|
940
|
+
kind: "source",
|
|
984
941
|
path: preparedFile.file.path,
|
|
985
942
|
planned: 0,
|
|
986
943
|
preparedFile,
|
|
@@ -1047,29 +1004,34 @@ function toTargetIdentityInput(cwd, filePath, target) {
|
|
|
1047
1004
|
}
|
|
1048
1005
|
//#endregion
|
|
1049
1006
|
//#region src/core/run.ts
|
|
1050
|
-
var
|
|
1051
|
-
failure;
|
|
1007
|
+
var AlintRunCancelledError = class extends Error {
|
|
1052
1008
|
result;
|
|
1053
|
-
constructor(
|
|
1054
|
-
super(
|
|
1055
|
-
this.name = "
|
|
1056
|
-
this.failure = options.failure;
|
|
1009
|
+
constructor(result, cause) {
|
|
1010
|
+
super("Alint run cancelled.", { cause });
|
|
1011
|
+
this.name = "AlintRunCancelledError";
|
|
1057
1012
|
this.result = result;
|
|
1058
1013
|
}
|
|
1059
1014
|
};
|
|
1060
|
-
/**
|
|
1061
|
-
|
|
1062
|
-
*
|
|
1063
|
-
* Extends {@link AlintRunError} so existing handlers still receive the partial `result`, while
|
|
1064
|
-
* callers that treat cancellation differently from failure can test for this type.
|
|
1065
|
-
*/
|
|
1066
|
-
var AlintAbortError = class extends AlintRunError {
|
|
1015
|
+
/** Cancellation error carrying the partial result gathered before the abort. */
|
|
1016
|
+
var AlintAbortError = class extends AlintRunCancelledError {
|
|
1067
1017
|
constructor(result, options = {}) {
|
|
1068
|
-
super(
|
|
1018
|
+
super(result, options.cause);
|
|
1069
1019
|
this.name = "AlintAbortError";
|
|
1070
1020
|
}
|
|
1071
1021
|
};
|
|
1022
|
+
var AlintRunError = class extends Error {
|
|
1023
|
+
failures;
|
|
1024
|
+
result;
|
|
1025
|
+
constructor(message, result, options = {}) {
|
|
1026
|
+
super(message, { cause: options.cause });
|
|
1027
|
+
this.name = "AlintRunError";
|
|
1028
|
+
this.failures = options.failures ?? [];
|
|
1029
|
+
this.result = result;
|
|
1030
|
+
}
|
|
1031
|
+
};
|
|
1072
1032
|
async function runAlint(options = {}) {
|
|
1033
|
+
const timeoutMs = resolveRuleExecutionTimeout(options.runner?.timeoutMs);
|
|
1034
|
+
const concurrency = resolveRuleConcurrency(options.runner?.ruleConcurrency);
|
|
1073
1035
|
const cwd$1 = options.cwd ?? cwd();
|
|
1074
1036
|
const config = options.config ?? [];
|
|
1075
1037
|
const setupConfig = options.setupConfig ?? {
|
|
@@ -1077,8 +1039,6 @@ async function runAlint(options = {}) {
|
|
|
1077
1039
|
version: 1
|
|
1078
1040
|
};
|
|
1079
1041
|
const clock = Date.now;
|
|
1080
|
-
const diagnostics = [];
|
|
1081
|
-
const usage = createUsageAccumulator();
|
|
1082
1042
|
const src = createSourceRuntime();
|
|
1083
1043
|
const normalizedCacheConfig = normalizeRunnerCacheConfig(options.runner?.cache, cwd$1);
|
|
1084
1044
|
const cacheStore = await createCacheStore({
|
|
@@ -1115,14 +1075,13 @@ async function runAlint(options = {}) {
|
|
|
1115
1075
|
const registry = buildRuleRegistry(effectiveConfig);
|
|
1116
1076
|
const ruleRuntimes = createRuleRuntimes({
|
|
1117
1077
|
cwd: cwd$1,
|
|
1118
|
-
diagnostics,
|
|
1119
1078
|
effectiveAgent: effectiveConfig.agent,
|
|
1120
1079
|
effectiveSettings: effectiveConfig.settings,
|
|
1121
1080
|
options,
|
|
1081
|
+
progress: options.progress,
|
|
1122
1082
|
registry,
|
|
1123
1083
|
setupConfig,
|
|
1124
|
-
src
|
|
1125
|
-
usage
|
|
1084
|
+
src
|
|
1126
1085
|
});
|
|
1127
1086
|
return {
|
|
1128
1087
|
configHash: stableHash({
|
|
@@ -1150,14 +1109,13 @@ async function runAlint(options = {}) {
|
|
|
1150
1109
|
configHash: stableHash({ settings: effectiveConfig.settings }),
|
|
1151
1110
|
ruleRuntimes: createRuleRuntimes({
|
|
1152
1111
|
cwd: cwd$1,
|
|
1153
|
-
diagnostics,
|
|
1154
1112
|
effectiveAgent: effectiveConfig.agent,
|
|
1155
1113
|
effectiveSettings: effectiveConfig.settings,
|
|
1156
1114
|
options,
|
|
1115
|
+
progress: options.progress,
|
|
1157
1116
|
registry,
|
|
1158
1117
|
setupConfig,
|
|
1159
|
-
src
|
|
1160
|
-
usage
|
|
1118
|
+
src
|
|
1161
1119
|
}),
|
|
1162
1120
|
target
|
|
1163
1121
|
};
|
|
@@ -1166,181 +1124,146 @@ async function runAlint(options = {}) {
|
|
|
1166
1124
|
const projectConfig = resolvedProjectConfig.config;
|
|
1167
1125
|
const projectRuleRuntimes = resolvedProjectConfig.ignored ? [] : createRuleRuntimes({
|
|
1168
1126
|
cwd: cwd$1,
|
|
1169
|
-
diagnostics,
|
|
1170
1127
|
effectiveAgent: projectConfig.agent,
|
|
1171
1128
|
effectiveSettings: projectConfig.settings,
|
|
1172
1129
|
options,
|
|
1130
|
+
progress: options.progress,
|
|
1173
1131
|
registry: buildRuleRegistry(projectConfig),
|
|
1174
1132
|
setupConfig,
|
|
1175
|
-
src
|
|
1176
|
-
|
|
1133
|
+
src
|
|
1134
|
+
});
|
|
1135
|
+
const filePlans = createSourceExecutionPlans(files, cwd$1);
|
|
1136
|
+
const directoryPlans = createDirectoryExecutionPlans(directories, filePlans.length);
|
|
1137
|
+
const projectPlan = resolvedProjectConfig.ignored ? void 0 : createProjectExecutionPlan({
|
|
1138
|
+
configHash: stableHash({ settings: projectConfig.settings }),
|
|
1139
|
+
files,
|
|
1140
|
+
index: filePlans.length + directoryPlans.length + 1,
|
|
1141
|
+
root: cwd$1,
|
|
1142
|
+
ruleRuntimes: projectRuleRuntimes
|
|
1143
|
+
});
|
|
1144
|
+
const jobs = createRuleJobs([
|
|
1145
|
+
...filePlans,
|
|
1146
|
+
...directoryPlans,
|
|
1147
|
+
...projectPlan ? [projectPlan] : []
|
|
1148
|
+
]);
|
|
1149
|
+
const runStartedAt = clock();
|
|
1150
|
+
const settledOutcomes = new Array(jobs.length);
|
|
1151
|
+
let infrastructureError;
|
|
1152
|
+
let infrastructureFailed = false;
|
|
1153
|
+
options.progress?.onRunStart?.({
|
|
1154
|
+
jobsTotal: jobs.length,
|
|
1155
|
+
startedAt: runStartedAt
|
|
1177
1156
|
});
|
|
1178
|
-
|
|
1179
|
-
const counters = createRuleEndCounters();
|
|
1180
|
-
let filePlans = [];
|
|
1181
|
-
let directoryPlans = [];
|
|
1182
|
-
let projectPlan;
|
|
1183
|
-
let runStartedAt;
|
|
1184
|
-
let runError;
|
|
1157
|
+
for (const job of jobs) options.progress?.onJobQueued?.({ job: job.job });
|
|
1185
1158
|
try {
|
|
1186
|
-
|
|
1187
|
-
|
|
1188
|
-
|
|
1189
|
-
|
|
1190
|
-
|
|
1191
|
-
|
|
1192
|
-
|
|
1193
|
-
|
|
1194
|
-
|
|
1195
|
-
|
|
1196
|
-
|
|
1197
|
-
|
|
1198
|
-
|
|
1199
|
-
|
|
1200
|
-
|
|
1201
|
-
|
|
1202
|
-
|
|
1203
|
-
|
|
1204
|
-
|
|
1205
|
-
|
|
1206
|
-
|
|
1207
|
-
|
|
1208
|
-
|
|
1209
|
-
|
|
1210
|
-
|
|
1211
|
-
|
|
1212
|
-
|
|
1213
|
-
|
|
1214
|
-
|
|
1215
|
-
|
|
1216
|
-
|
|
1217
|
-
|
|
1218
|
-
|
|
1219
|
-
|
|
1220
|
-
|
|
1221
|
-
|
|
1222
|
-
|
|
1223
|
-
|
|
1224
|
-
|
|
1225
|
-
|
|
1226
|
-
|
|
1227
|
-
|
|
1228
|
-
plans: [directoryPlan],
|
|
1229
|
-
progress: options.progress,
|
|
1230
|
-
signal: options.signal,
|
|
1231
|
-
usage
|
|
1232
|
-
}));
|
|
1233
|
-
if (projectPlan) await executeTargetPlans({
|
|
1234
|
-
cache: cacheContext,
|
|
1235
|
-
cacheOnly: options.cacheOnly,
|
|
1236
|
-
clock,
|
|
1237
|
-
counters,
|
|
1238
|
-
diagnostics,
|
|
1239
|
-
filesTotal: inputsTotal,
|
|
1240
|
-
plans: [projectPlan],
|
|
1241
|
-
progress: options.progress,
|
|
1242
|
-
signal: options.signal,
|
|
1243
|
-
usage
|
|
1244
|
-
});
|
|
1245
|
-
} catch (error) {
|
|
1246
|
-
runError = error;
|
|
1159
|
+
let cursor = 0;
|
|
1160
|
+
const worker = async () => {
|
|
1161
|
+
while (cursor < jobs.length) {
|
|
1162
|
+
const index = cursor;
|
|
1163
|
+
cursor += 1;
|
|
1164
|
+
const job = jobs[index];
|
|
1165
|
+
if (options.signal?.aborted) {
|
|
1166
|
+
settledOutcomes[index] = {
|
|
1167
|
+
bucket: {
|
|
1168
|
+
diagnostics: [],
|
|
1169
|
+
usage: []
|
|
1170
|
+
},
|
|
1171
|
+
cache: "miss",
|
|
1172
|
+
job,
|
|
1173
|
+
state: "cancelled"
|
|
1174
|
+
};
|
|
1175
|
+
continue;
|
|
1176
|
+
}
|
|
1177
|
+
try {
|
|
1178
|
+
const startedAt = clock();
|
|
1179
|
+
options.progress?.onJobStart?.({
|
|
1180
|
+
job: job.job,
|
|
1181
|
+
startedAt
|
|
1182
|
+
});
|
|
1183
|
+
settledOutcomes[index] = await executeRuleJob(job, {
|
|
1184
|
+
cache: cacheContext,
|
|
1185
|
+
cacheOnly: options.cacheOnly,
|
|
1186
|
+
clock,
|
|
1187
|
+
progress: options.progress,
|
|
1188
|
+
runSignal: options.signal,
|
|
1189
|
+
startedAt,
|
|
1190
|
+
timeoutMs
|
|
1191
|
+
});
|
|
1192
|
+
} catch (error) {
|
|
1193
|
+
if (!infrastructureFailed) {
|
|
1194
|
+
infrastructureError = error;
|
|
1195
|
+
infrastructureFailed = true;
|
|
1196
|
+
}
|
|
1197
|
+
}
|
|
1198
|
+
}
|
|
1199
|
+
};
|
|
1200
|
+
await Promise.all(Array.from({ length: Math.min(concurrency, jobs.length) }, worker));
|
|
1247
1201
|
} finally {
|
|
1248
1202
|
if (!options.cacheOnly) await reconcileCache(filePlans, cacheContext);
|
|
1249
|
-
try {
|
|
1250
|
-
options.progress?.onRunEnd?.({
|
|
1251
|
-
...counters.snapshot(planned),
|
|
1252
|
-
diagnostics,
|
|
1253
|
-
endedAt: clock(),
|
|
1254
|
-
startedAt: runStartedAt ?? clock(),
|
|
1255
|
-
usage: usage.toJSON()
|
|
1256
|
-
});
|
|
1257
|
-
} catch (error) {
|
|
1258
|
-
runError ??= error;
|
|
1259
|
-
}
|
|
1260
1203
|
}
|
|
1204
|
+
const outcomes = Array.from({ length: jobs.length }, (_, index) => settledOutcomes[index] ?? {
|
|
1205
|
+
bucket: {
|
|
1206
|
+
diagnostics: [],
|
|
1207
|
+
usage: []
|
|
1208
|
+
},
|
|
1209
|
+
cache: "miss",
|
|
1210
|
+
job: jobs[index],
|
|
1211
|
+
state: "cancelled"
|
|
1212
|
+
});
|
|
1213
|
+
const failedOutcomes = outcomes.filter((outcome) => outcome.state === "failed");
|
|
1214
|
+
const failures = failedOutcomes.map((outcome) => outcome.failure);
|
|
1261
1215
|
const result = {
|
|
1262
|
-
diagnostics,
|
|
1263
|
-
execution:
|
|
1264
|
-
usage:
|
|
1216
|
+
diagnostics: outcomes.flatMap((outcome) => outcome.bucket.diagnostics),
|
|
1217
|
+
execution: executionCounts(outcomes),
|
|
1218
|
+
usage: runUsage(outcomes)
|
|
1265
1219
|
};
|
|
1266
|
-
|
|
1267
|
-
|
|
1268
|
-
|
|
1269
|
-
|
|
1270
|
-
|
|
1271
|
-
|
|
1272
|
-
function addTokenCount(base, value) {
|
|
1273
|
-
return typeof value === "number" && Number.isFinite(value) ? base + value : base;
|
|
1274
|
-
}
|
|
1275
|
-
function calculatePlannedExecutions(filePlans) {
|
|
1276
|
-
return filePlans.reduce((total, filePlan) => total + filePlan.planned, 0);
|
|
1277
|
-
}
|
|
1278
|
-
function countEnabledRuleIds(files, directories, projectRuleRuntimes) {
|
|
1279
|
-
const ids = /* @__PURE__ */ new Set();
|
|
1280
|
-
for (const file of files) for (const runtime of file.ruleRuntimes) ids.add(runtime.enabledRule.id);
|
|
1281
|
-
for (const directory of directories) for (const runtime of directory.ruleRuntimes) ids.add(runtime.enabledRule.id);
|
|
1282
|
-
for (const runtime of projectRuleRuntimes) ids.add(runtime.enabledRule.id);
|
|
1283
|
-
return ids.size;
|
|
1284
|
-
}
|
|
1285
|
-
function createAlintRunError(error, result) {
|
|
1286
|
-
if (error instanceof AlintRunError) return error;
|
|
1287
|
-
if (error instanceof AlintRuleExecutionError) return new AlintRunError(error.message, result, {
|
|
1288
|
-
cause: errorCauseFrom(error),
|
|
1289
|
-
failure: error.failure
|
|
1220
|
+
options.progress?.onRunEnd?.({
|
|
1221
|
+
diagnostics: result.diagnostics,
|
|
1222
|
+
endedAt: clock(),
|
|
1223
|
+
execution: result.execution,
|
|
1224
|
+
startedAt: runStartedAt,
|
|
1225
|
+
usage: result.usage
|
|
1290
1226
|
});
|
|
1291
|
-
|
|
1292
|
-
}
|
|
1293
|
-
|
|
1294
|
-
|
|
1295
|
-
|
|
1296
|
-
|
|
1297
|
-
|
|
1298
|
-
return {
|
|
1299
|
-
cache() {
|
|
1300
|
-
cached += 1;
|
|
1301
|
-
},
|
|
1302
|
-
complete() {
|
|
1303
|
-
completed += 1;
|
|
1304
|
-
},
|
|
1305
|
-
error() {
|
|
1306
|
-
errored += 1;
|
|
1307
|
-
},
|
|
1308
|
-
skip() {
|
|
1309
|
-
skipped += 1;
|
|
1310
|
-
},
|
|
1311
|
-
snapshot(planned) {
|
|
1312
|
-
return {
|
|
1313
|
-
cached,
|
|
1314
|
-
completed,
|
|
1315
|
-
errored,
|
|
1316
|
-
planned,
|
|
1317
|
-
skipped
|
|
1318
|
-
};
|
|
1319
|
-
}
|
|
1320
|
-
};
|
|
1227
|
+
if (infrastructureFailed) throw infrastructureError;
|
|
1228
|
+
if (options.signal?.aborted) throw new AlintAbortError(result, { cause: options.signal.reason });
|
|
1229
|
+
if (failures.length > 0) throw new AlintRunError(`${failures.length} rule execution${failures.length === 1 ? "" : "s"} failed.`, result, {
|
|
1230
|
+
cause: new AggregateError(failedOutcomes.map((outcome) => outcome.cause), "Rule execution failures."),
|
|
1231
|
+
failures
|
|
1232
|
+
});
|
|
1233
|
+
return result;
|
|
1321
1234
|
}
|
|
1322
1235
|
function createRuleRuntimes(options) {
|
|
1323
|
-
const agent = options.effectiveAgent ? withAgentRetry(options.effectiveAgent, options.options.runner?.agentRetries) : void 0;
|
|
1324
1236
|
return options.registry.enabledRules.map((enabledRule) => {
|
|
1325
1237
|
const executionState = new AsyncLocalStorage();
|
|
1326
1238
|
const context = {
|
|
1327
|
-
agent
|
|
1239
|
+
agent: options.effectiveAgent ? withAgentRetry((request) => options.effectiveAgent({
|
|
1240
|
+
...request,
|
|
1241
|
+
signal: combineAbortSignals(executionState.getStore()?.signal, request.signal)
|
|
1242
|
+
}), options.options.runner?.agentRetries) : void 0,
|
|
1328
1243
|
cwd: options.cwd,
|
|
1329
1244
|
id: enabledRule.id,
|
|
1330
1245
|
localId: enabledRule.localId,
|
|
1331
1246
|
logger: { debug: () => {} },
|
|
1332
1247
|
metering: { recordUsage: (record) => {
|
|
1333
|
-
const
|
|
1248
|
+
const state = executionState.getStore();
|
|
1249
|
+
if (!state) throw new Error("Cannot record usage outside an active rule job.");
|
|
1250
|
+
const usageRecord = {
|
|
1334
1251
|
...record,
|
|
1335
1252
|
ruleId: record.ruleId ?? enabledRule.id
|
|
1336
|
-
}
|
|
1337
|
-
|
|
1338
|
-
|
|
1339
|
-
|
|
1340
|
-
|
|
1341
|
-
|
|
1342
|
-
|
|
1343
|
-
})
|
|
1253
|
+
};
|
|
1254
|
+
state.bucket.usage.push(usageRecord);
|
|
1255
|
+
try {
|
|
1256
|
+
options.progress?.onUsage?.({
|
|
1257
|
+
job: state.job,
|
|
1258
|
+
record: usageRecord
|
|
1259
|
+
});
|
|
1260
|
+
} catch (cause) {
|
|
1261
|
+
if (!state.reporterFailed) {
|
|
1262
|
+
state.reporterCause = cause;
|
|
1263
|
+
state.reporterFailed = true;
|
|
1264
|
+
}
|
|
1265
|
+
throw cause;
|
|
1266
|
+
}
|
|
1344
1267
|
} },
|
|
1345
1268
|
model: async (selector) => {
|
|
1346
1269
|
const request = options.options.modelOverride ?? (typeof selector === "string" ? selector : void 0);
|
|
@@ -1357,10 +1280,11 @@ function createRuleRuntimes(options) {
|
|
|
1357
1280
|
outputLanguage: options.options.outputLanguage,
|
|
1358
1281
|
report: (descriptor) => {
|
|
1359
1282
|
const state = executionState.getStore();
|
|
1360
|
-
|
|
1283
|
+
if (!state) throw new Error("Cannot report a diagnostic outside an active rule job.");
|
|
1284
|
+
const filePath = descriptor.filePath ?? state.activeFilePath;
|
|
1361
1285
|
if (!filePath) throw new Error(`Diagnostic for rule "${enabledRule.id}" is missing filePath.`);
|
|
1362
|
-
const diagnosticModel = state
|
|
1363
|
-
|
|
1286
|
+
const diagnosticModel = state.currentModel ? { ...state.currentModel } : void 0;
|
|
1287
|
+
state.currentModel = void 0;
|
|
1364
1288
|
const diagnostic = {
|
|
1365
1289
|
evidence: descriptor.evidence,
|
|
1366
1290
|
filePath,
|
|
@@ -1370,16 +1294,24 @@ function createRuleRuntimes(options) {
|
|
|
1370
1294
|
ruleId: enabledRule.id,
|
|
1371
1295
|
severity: enabledRule.severity
|
|
1372
1296
|
};
|
|
1373
|
-
|
|
1374
|
-
|
|
1375
|
-
|
|
1376
|
-
|
|
1377
|
-
|
|
1378
|
-
|
|
1379
|
-
})
|
|
1297
|
+
state.bucket.diagnostics.push(diagnostic);
|
|
1298
|
+
try {
|
|
1299
|
+
options.progress?.onDiagnostic?.({
|
|
1300
|
+
diagnostic,
|
|
1301
|
+
job: state.job
|
|
1302
|
+
});
|
|
1303
|
+
} catch (cause) {
|
|
1304
|
+
if (!state.reporterFailed) {
|
|
1305
|
+
state.reporterCause = cause;
|
|
1306
|
+
state.reporterFailed = true;
|
|
1307
|
+
}
|
|
1308
|
+
throw cause;
|
|
1309
|
+
}
|
|
1380
1310
|
},
|
|
1381
1311
|
settings: options.effectiveSettings,
|
|
1382
|
-
signal
|
|
1312
|
+
get signal() {
|
|
1313
|
+
return executionState.getStore()?.signal;
|
|
1314
|
+
},
|
|
1383
1315
|
src: options.src
|
|
1384
1316
|
};
|
|
1385
1317
|
return {
|
|
@@ -1399,47 +1331,19 @@ function createRuleRuntimes(options) {
|
|
|
1399
1331
|
};
|
|
1400
1332
|
});
|
|
1401
1333
|
}
|
|
1402
|
-
function
|
|
1403
|
-
const
|
|
1404
|
-
|
|
1405
|
-
|
|
1406
|
-
|
|
1407
|
-
|
|
1408
|
-
|
|
1409
|
-
|
|
1410
|
-
|
|
1411
|
-
|
|
1412
|
-
toJSON() {
|
|
1413
|
-
const cachedUsage = cached.toJSON();
|
|
1414
|
-
return {
|
|
1415
|
-
...live.toJSON(),
|
|
1416
|
-
...cachedUsage.records.length > 0 ? { cached: cachedUsage } : {}
|
|
1417
|
-
};
|
|
1418
|
-
}
|
|
1419
|
-
};
|
|
1420
|
-
}
|
|
1421
|
-
function createUsageTotals() {
|
|
1422
|
-
const records = [];
|
|
1423
|
-
let inputTokens = 0;
|
|
1424
|
-
let outputTokens = 0;
|
|
1425
|
-
let totalTokens = 0;
|
|
1426
|
-
return {
|
|
1427
|
-
record(record) {
|
|
1428
|
-
records.push(record);
|
|
1429
|
-
inputTokens = addTokenCount(inputTokens, record.inputTokens);
|
|
1430
|
-
outputTokens = addTokenCount(outputTokens, record.outputTokens);
|
|
1431
|
-
totalTokens = addTokenCount(totalTokens, record.totalTokens);
|
|
1432
|
-
return record;
|
|
1433
|
-
},
|
|
1434
|
-
toJSON() {
|
|
1435
|
-
return {
|
|
1436
|
-
inputTokens,
|
|
1437
|
-
outputTokens,
|
|
1438
|
-
records,
|
|
1439
|
-
totalTokens
|
|
1440
|
-
};
|
|
1441
|
-
}
|
|
1334
|
+
function executionCounts(outcomes) {
|
|
1335
|
+
const counts = {
|
|
1336
|
+
cached: 0,
|
|
1337
|
+
cancelled: 0,
|
|
1338
|
+
completed: 0,
|
|
1339
|
+
failed: 0,
|
|
1340
|
+
planned: outcomes.length,
|
|
1341
|
+
queued: 0,
|
|
1342
|
+
running: 0,
|
|
1343
|
+
skipped: 0
|
|
1442
1344
|
};
|
|
1345
|
+
for (const outcome of outcomes) counts[outcome.state] += 1;
|
|
1346
|
+
return counts;
|
|
1443
1347
|
}
|
|
1444
1348
|
function mergeCapabilities(base, extra) {
|
|
1445
1349
|
if (!base && !extra) return;
|
|
@@ -1475,28 +1379,19 @@ async function reconcileCache(filePlans, cacheContext) {
|
|
|
1475
1379
|
await cacheContext.store.reconcile();
|
|
1476
1380
|
} catch {}
|
|
1477
1381
|
}
|
|
1478
|
-
function
|
|
1479
|
-
|
|
1480
|
-
|
|
1481
|
-
|
|
1482
|
-
|
|
1483
|
-
|
|
1484
|
-
const
|
|
1485
|
-
|
|
1486
|
-
|
|
1487
|
-
|
|
1488
|
-
|
|
1489
|
-
|
|
1490
|
-
|
|
1491
|
-
await runItem(items[currentIndex]);
|
|
1492
|
-
} catch (error) {
|
|
1493
|
-
firstError ??= error;
|
|
1494
|
-
return;
|
|
1495
|
-
}
|
|
1496
|
-
}
|
|
1497
|
-
}
|
|
1498
|
-
await Promise.all(Array.from({ length: workerCount }, () => runWorker()));
|
|
1499
|
-
if (firstError !== void 0) throw firstError;
|
|
1382
|
+
function resolveRuleConcurrency(ruleConcurrency) {
|
|
1383
|
+
if (ruleConcurrency === void 0) return 4;
|
|
1384
|
+
if (!Number.isFinite(ruleConcurrency) || !Number.isInteger(ruleConcurrency) || ruleConcurrency <= 0) throw new TypeError("Rule execution concurrency must be a finite positive integer.");
|
|
1385
|
+
return ruleConcurrency;
|
|
1386
|
+
}
|
|
1387
|
+
function runUsage(outcomes) {
|
|
1388
|
+
const live = [];
|
|
1389
|
+
const cached = [];
|
|
1390
|
+
for (const outcome of outcomes) (outcome.state === "cached" ? cached : live).push(...outcome.bucket.usage);
|
|
1391
|
+
return {
|
|
1392
|
+
...usageTotals(live),
|
|
1393
|
+
...cached.length > 0 ? { cached: usageTotals(cached) } : {}
|
|
1394
|
+
};
|
|
1500
1395
|
}
|
|
1501
1396
|
function toDiagnosticModel(model, request) {
|
|
1502
1397
|
return {
|
|
@@ -1505,12 +1400,20 @@ function toDiagnosticModel(model, request) {
|
|
|
1505
1400
|
resolvedId: model.id
|
|
1506
1401
|
};
|
|
1507
1402
|
}
|
|
1508
|
-
function
|
|
1403
|
+
function usageTotals(records) {
|
|
1404
|
+
let inputTokens = 0;
|
|
1405
|
+
let outputTokens = 0;
|
|
1406
|
+
let totalTokens = 0;
|
|
1407
|
+
for (const record of records) {
|
|
1408
|
+
if (record.inputTokens != null && Number.isFinite(record.inputTokens)) inputTokens += record.inputTokens;
|
|
1409
|
+
if (record.outputTokens != null && Number.isFinite(record.outputTokens)) outputTokens += record.outputTokens;
|
|
1410
|
+
if (record.totalTokens != null && Number.isFinite(record.totalTokens)) totalTokens += record.totalTokens;
|
|
1411
|
+
}
|
|
1509
1412
|
return {
|
|
1510
|
-
|
|
1511
|
-
|
|
1512
|
-
|
|
1513
|
-
|
|
1413
|
+
inputTokens,
|
|
1414
|
+
outputTokens,
|
|
1415
|
+
records: [...records],
|
|
1416
|
+
totalTokens
|
|
1514
1417
|
};
|
|
1515
1418
|
}
|
|
1516
1419
|
//#endregion
|
|
@@ -1525,4 +1428,4 @@ function defineRule(rule) {
|
|
|
1525
1428
|
return rule;
|
|
1526
1429
|
}
|
|
1527
1430
|
//#endregion
|
|
1528
|
-
export { AlintRunError, buildRuleRegistry, createBuiltInLanguageRegistry, createSourceFile, createSourceRuntime, defineConfig, definePlugin, defineRule, hasDiscoveryFilePatterns, matchesDiscoveryFile, normalizeConfig, registerLanguage, resolveConfigForDirectory, resolveConfigForFile, resolveConfigForProject, resolveLanguage, resolveModel, runAlint, sliceLines, sliceRange };
|
|
1431
|
+
export { AlintAbortError, AlintRunCancelledError, AlintRunError, buildRuleRegistry, createBuiltInLanguageRegistry, createSourceFile, createSourceRuntime, defineConfig, definePlugin, defineRule, hasDiscoveryFilePatterns, matchesDiscoveryFile, normalizeConfig, registerLanguage, resolveConfigForDirectory, resolveConfigForFile, resolveConfigForProject, resolveLanguage, resolveModel, runAlint, sliceLines, sliceRange };
|