@alint-js/config 0.0.21 → 0.0.23
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/index.d.mts +93 -1
- package/dist/index.mjs +444 -14
- package/package.json +6 -7
package/dist/index.d.mts
CHANGED
|
@@ -69,6 +69,98 @@ declare function getProjectPluginStorePath(cwd: string): string;
|
|
|
69
69
|
declare function getProjectSetupConfigPath(cwd: string): string;
|
|
70
70
|
declare function getStatsDir(env?: NodeJS.ProcessEnv, options?: GlobalSetupConfigPathOptions): string;
|
|
71
71
|
//#endregion
|
|
72
|
+
//#region src/plugins/declarative/types.d.ts
|
|
73
|
+
declare const builtInAgentNames: readonly ["basic-structured", "basic-coding-agent"];
|
|
74
|
+
declare const declarativeRuleFilePattern = "**/rule.alint.{toml,yaml,yml,json,jsonc,json5}";
|
|
75
|
+
type BuiltInAgentName = typeof builtInAgentNames[number];
|
|
76
|
+
interface DeclarativeFinding {
|
|
77
|
+
confidence?: 'high' | 'low' | 'medium';
|
|
78
|
+
filePath?: string;
|
|
79
|
+
line: number;
|
|
80
|
+
message: string;
|
|
81
|
+
suggestion?: string;
|
|
82
|
+
}
|
|
83
|
+
interface DeclarativeFindingResponse {
|
|
84
|
+
findings: DeclarativeFinding[];
|
|
85
|
+
}
|
|
86
|
+
declare const declarativeFindingSchema: import("valibot").SchemaWithPipe<readonly [import("valibot").ObjectSchema<{
|
|
87
|
+
readonly confidence: import("valibot").OptionalSchema<import("valibot").SchemaWithPipe<readonly [import("valibot").PicklistSchema<["high", "medium", "low"], undefined>, import("valibot").DescriptionAction<"high" | "medium" | "low", "Confidence in this finding. Use exactly \"high\", \"medium\", or \"low\" when confidence is known.">]>, undefined>;
|
|
88
|
+
readonly filePath: import("valibot").OptionalSchema<import("valibot").SchemaWithPipe<readonly [import("valibot").StringSchema<undefined>, import("valibot").DescriptionAction<string, "Path to the file that owns this finding. Omit when the finding belongs to the reviewed target file.">]>, undefined>;
|
|
89
|
+
readonly line: import("valibot").SchemaWithPipe<readonly [import("valibot").NumberSchema<undefined>, import("valibot").DescriptionAction<number, "Use the left-column line number from the numbered source block.">]>;
|
|
90
|
+
readonly message: import("valibot").SchemaWithPipe<readonly [import("valibot").StringSchema<undefined>, import("valibot").DescriptionAction<string, "Human-readable diagnostic message describing the issue.">]>;
|
|
91
|
+
readonly suggestion: import("valibot").OptionalSchema<import("valibot").SchemaWithPipe<readonly [import("valibot").StringSchema<undefined>, import("valibot").DescriptionAction<string, "Concrete remediation direction for the finding.">]>, undefined>;
|
|
92
|
+
}, undefined>, import("valibot").DescriptionAction<{
|
|
93
|
+
confidence?: "high" | "medium" | "low" | undefined;
|
|
94
|
+
filePath?: string | undefined;
|
|
95
|
+
line: number;
|
|
96
|
+
message: string;
|
|
97
|
+
suggestion?: string | undefined;
|
|
98
|
+
}, "One declarative rule finding.">]>;
|
|
99
|
+
declare const declarativeFindingResponseSchema: import("valibot").SchemaWithPipe<readonly [import("valibot").ObjectSchema<{
|
|
100
|
+
readonly findings: import("valibot").SchemaWithPipe<readonly [import("valibot").ArraySchema<import("valibot").SchemaWithPipe<readonly [import("valibot").ObjectSchema<{
|
|
101
|
+
readonly confidence: import("valibot").OptionalSchema<import("valibot").SchemaWithPipe<readonly [import("valibot").PicklistSchema<["high", "medium", "low"], undefined>, import("valibot").DescriptionAction<"high" | "medium" | "low", "Confidence in this finding. Use exactly \"high\", \"medium\", or \"low\" when confidence is known.">]>, undefined>;
|
|
102
|
+
readonly filePath: import("valibot").OptionalSchema<import("valibot").SchemaWithPipe<readonly [import("valibot").StringSchema<undefined>, import("valibot").DescriptionAction<string, "Path to the file that owns this finding. Omit when the finding belongs to the reviewed target file.">]>, undefined>;
|
|
103
|
+
readonly line: import("valibot").SchemaWithPipe<readonly [import("valibot").NumberSchema<undefined>, import("valibot").DescriptionAction<number, "Use the left-column line number from the numbered source block.">]>;
|
|
104
|
+
readonly message: import("valibot").SchemaWithPipe<readonly [import("valibot").StringSchema<undefined>, import("valibot").DescriptionAction<string, "Human-readable diagnostic message describing the issue.">]>;
|
|
105
|
+
readonly suggestion: import("valibot").OptionalSchema<import("valibot").SchemaWithPipe<readonly [import("valibot").StringSchema<undefined>, import("valibot").DescriptionAction<string, "Concrete remediation direction for the finding.">]>, undefined>;
|
|
106
|
+
}, undefined>, import("valibot").DescriptionAction<{
|
|
107
|
+
confidence?: "high" | "medium" | "low" | undefined;
|
|
108
|
+
filePath?: string | undefined;
|
|
109
|
+
line: number;
|
|
110
|
+
message: string;
|
|
111
|
+
suggestion?: string | undefined;
|
|
112
|
+
}, "One declarative rule finding.">]>, undefined>, import("valibot").DescriptionAction<{
|
|
113
|
+
confidence?: "high" | "medium" | "low" | undefined;
|
|
114
|
+
filePath?: string | undefined;
|
|
115
|
+
line: number;
|
|
116
|
+
message: string;
|
|
117
|
+
suggestion?: string | undefined;
|
|
118
|
+
}[], "All findings for the declarative rule. Return an empty array when there are no issues.">]>;
|
|
119
|
+
}, undefined>, import("valibot").DescriptionAction<{
|
|
120
|
+
findings: {
|
|
121
|
+
confidence?: "high" | "medium" | "low" | undefined;
|
|
122
|
+
filePath?: string | undefined;
|
|
123
|
+
line: number;
|
|
124
|
+
message: string;
|
|
125
|
+
suggestion?: string | undefined;
|
|
126
|
+
}[];
|
|
127
|
+
}, "Structured declarative rule findings.">]>;
|
|
128
|
+
interface DeclarativeRuleDefinition {
|
|
129
|
+
builtInAgent: BuiltInAgentName;
|
|
130
|
+
excludeFiles: string[];
|
|
131
|
+
filePath: string;
|
|
132
|
+
includeFiles?: string[];
|
|
133
|
+
instruction: string;
|
|
134
|
+
name: string;
|
|
135
|
+
}
|
|
136
|
+
declare function isBuiltInAgentName(value: unknown): value is BuiltInAgentName;
|
|
137
|
+
//#endregion
|
|
138
|
+
//#region src/plugins/declarative/parse.d.ts
|
|
139
|
+
interface LoadDeclarativeRulesOptions {
|
|
140
|
+
alias: string;
|
|
141
|
+
root: string;
|
|
142
|
+
}
|
|
143
|
+
declare function hasDeclarativeRuleFiles(root: string): Promise<boolean>;
|
|
144
|
+
declare function loadDeclarativeRules(options: LoadDeclarativeRulesOptions): Promise<DeclarativeRuleDefinition[]>;
|
|
145
|
+
//#endregion
|
|
146
|
+
//#region src/plugins/declarative/plugin.d.ts
|
|
147
|
+
interface CreateDeclarativePluginOptions {
|
|
148
|
+
rules: readonly DeclarativeRuleDefinition[];
|
|
149
|
+
}
|
|
150
|
+
declare function createDeclarativePlugin(options: CreateDeclarativePluginOptions): PluginDefinition;
|
|
151
|
+
//#endregion
|
|
152
|
+
//#region src/plugins/declarative/scope.d.ts
|
|
153
|
+
interface CreateReportScopeOptions {
|
|
154
|
+
cwd: string;
|
|
155
|
+
excludeFiles: readonly string[];
|
|
156
|
+
includeFiles?: readonly string[];
|
|
157
|
+
targetFilePath?: string;
|
|
158
|
+
}
|
|
159
|
+
interface ReportScope {
|
|
160
|
+
canReport: (filePath: string | undefined) => boolean;
|
|
161
|
+
}
|
|
162
|
+
declare function createReportScope(options: CreateReportScopeOptions): ReportScope;
|
|
163
|
+
//#endregion
|
|
72
164
|
//#region src/plugins/types.d.ts
|
|
73
165
|
interface DirectoryPluginLockEntry {
|
|
74
166
|
alias: string;
|
|
@@ -153,4 +245,4 @@ declare function stringifySetupConfigToml(config: SetupConfig$1): string;
|
|
|
153
245
|
//#region src/setup/write.d.ts
|
|
154
246
|
declare function writeSetupConfig(filePath: string, config: SetupConfig$1): Promise<void>;
|
|
155
247
|
//#endregion
|
|
156
|
-
export { type AlintConfig, type DirectoryPluginLockEntry, type GlobalSetupConfigPathOptions, type ModelSize, type ParseStaticConfigOptions, type ParsedDirectoryPluginLockEntry, type ParsedPluginLockEntry, type ParsedPluginLockFile, type ParsedPluginSpecifier, type ParsedRegistryPluginLockEntry, type ParsedStaticConfig, type ParsedStaticConfigGroup, type PluginLockEntry, type PluginLockFile, type ProviderDefinition, type ProviderType, type RegistryPluginLockEntry, type RunnerConfig, type RunnerStatsConfig, type SetupConfig, type SetupModelDefinition, type StaticConfigInput, type StaticConfigItem, type StaticPluginInstallOptions, type StaticPluginInstallResult, type StaticPluginReference, type StaticPluginResolver, type ToAlintConfigOptions, createEmptyPluginLockFile, emptySetupConfig, getGlobalSetupConfigPath, getProjectPluginLockPath, getProjectPluginStorePath, getProjectSetupConfigPath, getStatsDir, ignorePatternsAIAgents, ignorePatternsBuildOutputs, ignorePatternsCaches, ignorePatternsCommon, ignorePatternsEslintDefaults, ignorePatternsGenerated, installStaticPlugins, listMissing, listUnresolved, loadAlintConfig, loadPluginLockFile, loadSetupConfig, loadStaticConfig, mergeSetupConfigs, parsePluginLockFile, parsePluginSpecifier, parseSetupConfigToml, parseStaticConfig, stringifySetupConfigToml, toAlintConfig, writePluginLockFile, writeSetupConfig };
|
|
248
|
+
export { type AlintConfig, BuiltInAgentName, CreateDeclarativePluginOptions, CreateReportScopeOptions, DeclarativeFinding, DeclarativeFindingResponse, DeclarativeRuleDefinition, type DirectoryPluginLockEntry, type GlobalSetupConfigPathOptions, LoadDeclarativeRulesOptions, type ModelSize, type ParseStaticConfigOptions, type ParsedDirectoryPluginLockEntry, type ParsedPluginLockEntry, type ParsedPluginLockFile, type ParsedPluginSpecifier, type ParsedRegistryPluginLockEntry, type ParsedStaticConfig, type ParsedStaticConfigGroup, type PluginLockEntry, type PluginLockFile, type ProviderDefinition, type ProviderType, type RegistryPluginLockEntry, ReportScope, type RunnerConfig, type RunnerStatsConfig, type SetupConfig, type SetupModelDefinition, type StaticConfigInput, type StaticConfigItem, type StaticPluginInstallOptions, type StaticPluginInstallResult, type StaticPluginReference, type StaticPluginResolver, type ToAlintConfigOptions, builtInAgentNames, createDeclarativePlugin, createEmptyPluginLockFile, createReportScope, declarativeFindingResponseSchema, declarativeFindingSchema, declarativeRuleFilePattern, emptySetupConfig, getGlobalSetupConfigPath, getProjectPluginLockPath, getProjectPluginStorePath, getProjectSetupConfigPath, getStatsDir, hasDeclarativeRuleFiles, ignorePatternsAIAgents, ignorePatternsBuildOutputs, ignorePatternsCaches, ignorePatternsCommon, ignorePatternsEslintDefaults, ignorePatternsGenerated, installStaticPlugins, isBuiltInAgentName, listMissing, listUnresolved, loadAlintConfig, loadDeclarativeRules, loadPluginLockFile, loadSetupConfig, loadStaticConfig, mergeSetupConfigs, parsePluginLockFile, parsePluginSpecifier, parseSetupConfigToml, parseStaticConfig, stringifySetupConfigToml, toAlintConfig, writePluginLockFile, writeSetupConfig };
|
package/dist/index.mjs
CHANGED
|
@@ -1,16 +1,20 @@
|
|
|
1
|
-
import { dirname, isAbsolute, join, normalize, posix, relative, resolve, sep, win32 } from "node:path";
|
|
1
|
+
import { basename, dirname, isAbsolute, join, normalize, posix, relative, resolve, sep, win32 } from "node:path";
|
|
2
2
|
import { loadConfig } from "c12";
|
|
3
3
|
import { createJiti } from "jiti/static";
|
|
4
4
|
import { createHash, randomUUID } from "node:crypto";
|
|
5
|
-
import { mkdir, readFile, realpath, rename, rm, stat, writeFile } from "node:fs/promises";
|
|
6
|
-
import { array, boolean, literal, looseObject, optional, parse, picklist, record, strictObject, string, tuple, union, unknown, variant } from "valibot";
|
|
5
|
+
import { access, mkdir, open, readFile, readdir, realpath, rename, rm, stat, writeFile } from "node:fs/promises";
|
|
6
|
+
import { array, boolean, check, description, literal, looseObject, number, object, optional, parse, picklist, pipe, record, strictObject, string, tuple, union, unknown, variant } from "valibot";
|
|
7
7
|
import process from "node:process";
|
|
8
8
|
import { homedir } from "node:os";
|
|
9
|
-
import { dirname as dirname$1, extname, join as join$1 } from "pathe";
|
|
9
|
+
import { dirname as dirname$1, extname, join as join$1, normalize as normalize$1 } from "pathe";
|
|
10
10
|
import { xdgConfig } from "xdg-basedir";
|
|
11
|
-
import { isError } from "@moeru/std/error";
|
|
12
|
-
import {
|
|
11
|
+
import { errorMessageFrom, isError } from "@moeru/std/error";
|
|
12
|
+
import { formatOutputLanguageInstruction, formatSourceWithLineNumbers, generateStructured, toolParametersFromSchema } from "@alint-js/core/structured-output";
|
|
13
|
+
import { createTools, listFiles } from "@alint-js/tools-fs";
|
|
14
|
+
import { chat, hasToolCall, or, rawTool, stepCountAtLeast, user } from "apeira";
|
|
13
15
|
import { Buffer } from "node:buffer";
|
|
16
|
+
import { minimatch } from "minimatch";
|
|
17
|
+
import { exports } from "resolve.exports";
|
|
14
18
|
import { createWriteStream } from "node:fs";
|
|
15
19
|
import { Readable } from "node:stream";
|
|
16
20
|
import { pipeline } from "node:stream/promises";
|
|
@@ -88,6 +92,386 @@ function parseIntegrity(integrity, specifier) {
|
|
|
88
92
|
};
|
|
89
93
|
}
|
|
90
94
|
//#endregion
|
|
95
|
+
//#region src/plugins/declarative/types.ts
|
|
96
|
+
const builtInAgentNames = ["basic-structured", "basic-coding-agent"];
|
|
97
|
+
const declarativeRuleFilePattern = "**/rule.alint.{toml,yaml,yml,json,jsonc,json5}";
|
|
98
|
+
const declarativeFindingSchema = pipe(object({
|
|
99
|
+
confidence: optional(pipe(picklist([
|
|
100
|
+
"high",
|
|
101
|
+
"medium",
|
|
102
|
+
"low"
|
|
103
|
+
]), description("Confidence in this finding. Use exactly \"high\", \"medium\", or \"low\" when confidence is known."))),
|
|
104
|
+
filePath: optional(pipe(string(), description("Path to the file that owns this finding. Omit when the finding belongs to the reviewed target file."))),
|
|
105
|
+
line: pipe(number(), description("Use the left-column line number from the numbered source block.")),
|
|
106
|
+
message: pipe(string(), description("Human-readable diagnostic message describing the issue.")),
|
|
107
|
+
suggestion: optional(pipe(string(), description("Concrete remediation direction for the finding.")))
|
|
108
|
+
}), description("One declarative rule finding."));
|
|
109
|
+
const declarativeFindingResponseSchema = pipe(object({ findings: pipe(array(declarativeFindingSchema), description("All findings for the declarative rule. Return an empty array when there are no issues.")) }), description("Structured declarative rule findings."));
|
|
110
|
+
function isBuiltInAgentName(value) {
|
|
111
|
+
return builtInAgentNames.includes(value);
|
|
112
|
+
}
|
|
113
|
+
//#endregion
|
|
114
|
+
//#region src/plugins/declarative/parse.ts
|
|
115
|
+
const declarativeRuleFileNamePattern = /^rule\.alint\.(?:toml|ya?ml|json|jsonc|json5)$/;
|
|
116
|
+
const declarativeRuleNamePattern = /^[\w.-]+$/;
|
|
117
|
+
const nonEmptyStringSchema = pipe(string(), check((value) => value.trim() !== "", "must be a non-empty string"));
|
|
118
|
+
const declarativeRuleFileSchema = object({
|
|
119
|
+
builtInAgent: picklist(builtInAgentNames),
|
|
120
|
+
excludeFiles: optional(array(string())),
|
|
121
|
+
includeFiles: optional(array(string())),
|
|
122
|
+
instruction: nonEmptyStringSchema,
|
|
123
|
+
name: pipe(nonEmptyStringSchema, check((value) => declarativeRuleNamePattern.test(value), "Declarative rule \"name\" must contain only letters, numbers, dots, underscores, and hyphens."))
|
|
124
|
+
});
|
|
125
|
+
async function hasDeclarativeRuleFiles(root) {
|
|
126
|
+
return (await findDeclarativeRuleFiles(root)).length > 0;
|
|
127
|
+
}
|
|
128
|
+
async function loadDeclarativeRules(options) {
|
|
129
|
+
const files = await findDeclarativeRuleFiles(options.root);
|
|
130
|
+
if (files.length === 0) throw new Error(`Directory plugin "${options.alias}" must contain package.json or rule.alint.* files.`);
|
|
131
|
+
const rules = [];
|
|
132
|
+
const filesByName = /* @__PURE__ */ new Map();
|
|
133
|
+
for (const file of files) {
|
|
134
|
+
const rule = await loadDeclarativeRuleFile(file);
|
|
135
|
+
const duplicateFile = filesByName.get(rule.name);
|
|
136
|
+
if (duplicateFile !== void 0) throw new Error(`Duplicate declarative rule name "${rule.name}" in ${file} and ${duplicateFile}.`);
|
|
137
|
+
filesByName.set(rule.name, file);
|
|
138
|
+
rules.push(rule);
|
|
139
|
+
}
|
|
140
|
+
return rules;
|
|
141
|
+
}
|
|
142
|
+
async function collectDeclarativeRuleFiles(directory, files) {
|
|
143
|
+
const entries = await readdir(directory, { withFileTypes: true });
|
|
144
|
+
await Promise.all(entries.map(async (entry) => {
|
|
145
|
+
const path = join(directory, entry.name);
|
|
146
|
+
if (entry.isDirectory()) {
|
|
147
|
+
await collectDeclarativeRuleFiles(path, files);
|
|
148
|
+
return;
|
|
149
|
+
}
|
|
150
|
+
if (entry.isFile() && declarativeRuleFileNamePattern.test(entry.name)) files.push(path);
|
|
151
|
+
}));
|
|
152
|
+
}
|
|
153
|
+
async function findDeclarativeRuleFiles(root) {
|
|
154
|
+
const files = [];
|
|
155
|
+
await collectDeclarativeRuleFiles(root, files);
|
|
156
|
+
return files.sort((left, right) => left.localeCompare(right));
|
|
157
|
+
}
|
|
158
|
+
function isPlainObject$3(value) {
|
|
159
|
+
return typeof value === "object" && value !== null && !Array.isArray(value);
|
|
160
|
+
}
|
|
161
|
+
async function loadDeclarativeRuleFile(filePath) {
|
|
162
|
+
const input = await loadDeclarativeRuleFileContent(filePath);
|
|
163
|
+
if (!isPlainObject$3(input)) throw new Error(`Declarative rule file ${filePath} must contain an object.`);
|
|
164
|
+
const parsed = parseDeclarativeRuleFileInput(input, filePath);
|
|
165
|
+
return {
|
|
166
|
+
builtInAgent: parsed.builtInAgent,
|
|
167
|
+
excludeFiles: parsed.excludeFiles ?? [],
|
|
168
|
+
filePath,
|
|
169
|
+
includeFiles: parsed.includeFiles,
|
|
170
|
+
instruction: parsed.instruction,
|
|
171
|
+
name: parsed.name
|
|
172
|
+
};
|
|
173
|
+
}
|
|
174
|
+
async function loadDeclarativeRuleFileContent(filePath) {
|
|
175
|
+
try {
|
|
176
|
+
return (await loadConfig({
|
|
177
|
+
configFile: basename(filePath),
|
|
178
|
+
cwd: dirname(filePath),
|
|
179
|
+
envName: false,
|
|
180
|
+
extend: false,
|
|
181
|
+
packageJson: false,
|
|
182
|
+
rcFile: false
|
|
183
|
+
})).config;
|
|
184
|
+
} catch (error) {
|
|
185
|
+
throw new Error(`Could not parse declarative rule file ${filePath}: ${errorMessageFrom(error) ?? "Unknown error"}`, { cause: error });
|
|
186
|
+
}
|
|
187
|
+
}
|
|
188
|
+
function parseDeclarativeRuleFileInput(input, filePath) {
|
|
189
|
+
try {
|
|
190
|
+
return parse(declarativeRuleFileSchema, input);
|
|
191
|
+
} catch (error) {
|
|
192
|
+
if (typeof input.builtInAgent === "string" && !isBuiltInAgentName(input.builtInAgent)) throw new Error(`Unknown builtInAgent "${input.builtInAgent}" in ${filePath}.`, { cause: error });
|
|
193
|
+
throw new Error(`Invalid declarative rule file ${filePath}: ${errorMessageFrom(error) ?? "Unknown error"}`, { cause: error });
|
|
194
|
+
}
|
|
195
|
+
}
|
|
196
|
+
//#endregion
|
|
197
|
+
//#region src/plugins/declarative/scope.ts
|
|
198
|
+
function createReportScope(options) {
|
|
199
|
+
const includeFiles = options.includeFiles;
|
|
200
|
+
const excludeFiles = options.excludeFiles;
|
|
201
|
+
const rawTargetFilePath = options.targetFilePath;
|
|
202
|
+
const hasTargetFilePath = rawTargetFilePath !== void 0;
|
|
203
|
+
const targetFilePath = rawTargetFilePath === void 0 ? void 0 : toScopedRelativePath(options.cwd, rawTargetFilePath);
|
|
204
|
+
return { canReport(filePath) {
|
|
205
|
+
if (filePath === void 0) return !hasTargetFilePath && includeFiles === void 0;
|
|
206
|
+
const relativePath = toScopedRelativePath(options.cwd, filePath);
|
|
207
|
+
if (relativePath === void 0) return false;
|
|
208
|
+
if (!(includeFiles === void 0 ? targetFilePath !== void 0 && relativePath === targetFilePath : includeFiles.some((pattern) => minimatch(relativePath, pattern, { dot: true })))) return false;
|
|
209
|
+
return !excludeFiles.some((pattern) => minimatch(relativePath, pattern, { dot: true }));
|
|
210
|
+
} };
|
|
211
|
+
}
|
|
212
|
+
function isOutsideScopePath(path) {
|
|
213
|
+
return path === ".." || path.startsWith("../") || isAbsolute(path) || win32.isAbsolute(path) || /^[A-Za-z]:/u.test(path);
|
|
214
|
+
}
|
|
215
|
+
function normalizePath(path) {
|
|
216
|
+
return normalize$1(path).replace(/^\.\//u, "");
|
|
217
|
+
}
|
|
218
|
+
function toScopedRelativePath(cwd, filePath) {
|
|
219
|
+
const path = normalizePath(relative(cwd, filePath));
|
|
220
|
+
if (isOutsideScopePath(path)) return;
|
|
221
|
+
return path;
|
|
222
|
+
}
|
|
223
|
+
//#endregion
|
|
224
|
+
//#region src/agents/presets/basic-structured.ts
|
|
225
|
+
const maxSupplementalFileBytes = 64 * 1024;
|
|
226
|
+
const maxSupplementalFiles = 12;
|
|
227
|
+
function createBasicStructuredRule(rule) {
|
|
228
|
+
return {
|
|
229
|
+
cache: rule.includeFiles === void 0 || rule.includeFiles.length === 0,
|
|
230
|
+
create: (ctx) => ({ async onTargetFile(target) {
|
|
231
|
+
const model = await ctx.model();
|
|
232
|
+
const supplementalFiles = await collectSupplementalFiles({
|
|
233
|
+
cwd: ctx.cwd,
|
|
234
|
+
includeFiles: rule.includeFiles,
|
|
235
|
+
logger: ctx.logger,
|
|
236
|
+
targetFilePath: target.file.path
|
|
237
|
+
});
|
|
238
|
+
const { findings } = await generateStructured({
|
|
239
|
+
createMessages: (retryFeedback) => createStructuredMessagesSync({
|
|
240
|
+
cwd: ctx.cwd,
|
|
241
|
+
includeFiles: rule.includeFiles,
|
|
242
|
+
instruction: rule.instruction,
|
|
243
|
+
outputLanguage: ctx.outputLanguage,
|
|
244
|
+
retryFeedback,
|
|
245
|
+
ruleFilePath: rule.filePath,
|
|
246
|
+
sourceText: target.file.text,
|
|
247
|
+
supplementalFiles,
|
|
248
|
+
targetFilePath: target.file.path
|
|
249
|
+
}),
|
|
250
|
+
logger: ctx.logger,
|
|
251
|
+
metering: ctx.metering,
|
|
252
|
+
model,
|
|
253
|
+
operation: `declarative-${rule.name}-structured`,
|
|
254
|
+
schema: declarativeFindingResponseSchema
|
|
255
|
+
});
|
|
256
|
+
reportDeclarativeFindings({
|
|
257
|
+
ctx,
|
|
258
|
+
excludeFiles: rule.excludeFiles,
|
|
259
|
+
findings,
|
|
260
|
+
includeFiles: rule.includeFiles,
|
|
261
|
+
targetFilePath: target.file.path
|
|
262
|
+
});
|
|
263
|
+
} })
|
|
264
|
+
};
|
|
265
|
+
}
|
|
266
|
+
function createStructuredMessagesSync(options) {
|
|
267
|
+
return [
|
|
268
|
+
{
|
|
269
|
+
content: options.instruction,
|
|
270
|
+
role: "system"
|
|
271
|
+
},
|
|
272
|
+
...options.retryFeedback ? [{
|
|
273
|
+
content: options.retryFeedback,
|
|
274
|
+
role: "user"
|
|
275
|
+
}] : [],
|
|
276
|
+
{
|
|
277
|
+
content: [
|
|
278
|
+
formatOutputLanguageInstruction(options.outputLanguage),
|
|
279
|
+
`Rule file path: ${options.ruleFilePath}`,
|
|
280
|
+
`Reviewed target file path: ${options.targetFilePath}`,
|
|
281
|
+
formatSupplementalFiles(options.cwd, options.supplementalFiles ?? []),
|
|
282
|
+
`Reviewed target source with line numbers:\n\n${formatSourceWithLineNumbers(options.sourceText)}`
|
|
283
|
+
].filter(Boolean).join("\n\n"),
|
|
284
|
+
role: "user"
|
|
285
|
+
}
|
|
286
|
+
];
|
|
287
|
+
}
|
|
288
|
+
function reportDeclarativeFindings(options) {
|
|
289
|
+
const scope = createReportScope({
|
|
290
|
+
cwd: options.ctx.cwd,
|
|
291
|
+
excludeFiles: options.excludeFiles,
|
|
292
|
+
includeFiles: options.includeFiles,
|
|
293
|
+
targetFilePath: options.targetFilePath
|
|
294
|
+
});
|
|
295
|
+
for (const finding of options.findings) {
|
|
296
|
+
const filePath = resolveFindingFilePath(options.ctx.cwd, options.targetFilePath, finding.filePath);
|
|
297
|
+
if (!scope.canReport(filePath)) {
|
|
298
|
+
options.ctx.logger.debug("Ignoring out-of-scope declarative finding", {
|
|
299
|
+
filePath,
|
|
300
|
+
message: finding.message
|
|
301
|
+
});
|
|
302
|
+
continue;
|
|
303
|
+
}
|
|
304
|
+
const evidence = createFindingEvidence(finding);
|
|
305
|
+
options.ctx.report({
|
|
306
|
+
...evidence ? { evidence } : {},
|
|
307
|
+
filePath,
|
|
308
|
+
loc: { start: {
|
|
309
|
+
column: 0,
|
|
310
|
+
line: finding.line
|
|
311
|
+
} },
|
|
312
|
+
message: finding.message
|
|
313
|
+
});
|
|
314
|
+
}
|
|
315
|
+
}
|
|
316
|
+
async function collectSupplementalFiles(options) {
|
|
317
|
+
if (options.includeFiles === void 0 || options.includeFiles.length === 0) return [];
|
|
318
|
+
const targetFilePath = resolve(options.targetFilePath);
|
|
319
|
+
const filePaths = (await listFiles(options.cwd, { patterns: options.includeFiles })).map((filePath) => resolve(filePath)).filter((filePath) => filePath !== targetFilePath).sort().slice(0, maxSupplementalFiles);
|
|
320
|
+
const files = [];
|
|
321
|
+
for (const filePath of filePaths) {
|
|
322
|
+
const content = await readSupplementalFile(filePath, options.logger);
|
|
323
|
+
if (content === void 0) continue;
|
|
324
|
+
files.push({
|
|
325
|
+
content,
|
|
326
|
+
filePath
|
|
327
|
+
});
|
|
328
|
+
}
|
|
329
|
+
return files;
|
|
330
|
+
}
|
|
331
|
+
function createFindingEvidence(finding) {
|
|
332
|
+
const evidence = {
|
|
333
|
+
...finding.confidence ? { confidence: finding.confidence } : {},
|
|
334
|
+
...finding.suggestion ? { suggestion: finding.suggestion } : {}
|
|
335
|
+
};
|
|
336
|
+
return Object.keys(evidence).length > 0 ? evidence : void 0;
|
|
337
|
+
}
|
|
338
|
+
function formatSupplementalFiles(cwd, files) {
|
|
339
|
+
if (files.length === 0) return;
|
|
340
|
+
return ["Supplemental files:", ...files.map((file) => [`File: ${relative(cwd, file.filePath)}`, file.content].join("\n\n"))].join("\n\n");
|
|
341
|
+
}
|
|
342
|
+
async function readSupplementalFile(filePath, logger) {
|
|
343
|
+
let handle;
|
|
344
|
+
try {
|
|
345
|
+
handle = await open(filePath, "r");
|
|
346
|
+
const buffer = Buffer.alloc(65537);
|
|
347
|
+
const { bytesRead } = await handle.read(buffer, 0, buffer.length, 0);
|
|
348
|
+
if (bytesRead > maxSupplementalFileBytes) {
|
|
349
|
+
logger?.debug("Skipping oversized declarative supplemental file", {
|
|
350
|
+
filePath,
|
|
351
|
+
maxBytes: maxSupplementalFileBytes
|
|
352
|
+
});
|
|
353
|
+
return;
|
|
354
|
+
}
|
|
355
|
+
return buffer.subarray(0, bytesRead).toString("utf8");
|
|
356
|
+
} catch (error) {
|
|
357
|
+
logger?.debug("Skipping unreadable declarative supplemental file", {
|
|
358
|
+
error,
|
|
359
|
+
filePath
|
|
360
|
+
});
|
|
361
|
+
return;
|
|
362
|
+
} finally {
|
|
363
|
+
await handle?.close();
|
|
364
|
+
}
|
|
365
|
+
}
|
|
366
|
+
function resolveFindingFilePath(cwd, targetFilePath, findingFilePath) {
|
|
367
|
+
if (findingFilePath === void 0 || findingFilePath.length === 0) return targetFilePath;
|
|
368
|
+
return isAbsolute(findingFilePath) ? findingFilePath : resolve(cwd, findingFilePath);
|
|
369
|
+
}
|
|
370
|
+
//#endregion
|
|
371
|
+
//#region src/agents/presets/basic-coding-agent.ts
|
|
372
|
+
const maxAgentSteps = 8;
|
|
373
|
+
const reportFindingsToolName = "report_findings";
|
|
374
|
+
function createBasicCodingAgentRule(rule) {
|
|
375
|
+
return {
|
|
376
|
+
cache: false,
|
|
377
|
+
create: (ctx) => ({ async onTargetFile(target) {
|
|
378
|
+
const model = await ctx.model();
|
|
379
|
+
const result = await createCodingAgent(model).run({
|
|
380
|
+
cwd: ctx.cwd,
|
|
381
|
+
instruction: rule.instruction,
|
|
382
|
+
outputLanguage: ctx.outputLanguage,
|
|
383
|
+
sourceText: target.file.text,
|
|
384
|
+
targetFilePath: target.file.path,
|
|
385
|
+
tools: createTools(ctx.cwd)
|
|
386
|
+
});
|
|
387
|
+
if (result.usage) ctx.metering.recordUsage({
|
|
388
|
+
filePath: target.file.path,
|
|
389
|
+
inputTokens: result.usage.inputTokens,
|
|
390
|
+
metadata: { operation: `declarative-${rule.name}-coding-agent` },
|
|
391
|
+
modelId: model.id,
|
|
392
|
+
outputTokens: result.usage.outputTokens,
|
|
393
|
+
providerId: model.provider.id,
|
|
394
|
+
ruleId: ctx.id,
|
|
395
|
+
totalTokens: result.usage.totalTokens
|
|
396
|
+
});
|
|
397
|
+
reportDeclarativeFindings({
|
|
398
|
+
ctx,
|
|
399
|
+
excludeFiles: rule.excludeFiles,
|
|
400
|
+
findings: result.findings,
|
|
401
|
+
includeFiles: rule.includeFiles,
|
|
402
|
+
targetFilePath: target.file.path
|
|
403
|
+
});
|
|
404
|
+
} })
|
|
405
|
+
};
|
|
406
|
+
}
|
|
407
|
+
function createCodingAgent(model, runner = chat({
|
|
408
|
+
baseURL: model.provider.endpoint,
|
|
409
|
+
headers: model.provider.headers,
|
|
410
|
+
model: model.id,
|
|
411
|
+
parallelToolCalls: false,
|
|
412
|
+
stopWhen: or(hasToolCall(reportFindingsToolName), stepCountAtLeast(maxAgentSteps)),
|
|
413
|
+
toolChoice: "required"
|
|
414
|
+
})) {
|
|
415
|
+
return { async run(options) {
|
|
416
|
+
let report;
|
|
417
|
+
const tools = options.tools.map((agentTool) => rawTool({
|
|
418
|
+
description: agentTool.description,
|
|
419
|
+
execute: async (input) => {
|
|
420
|
+
return await agentTool.execute(input) ?? "";
|
|
421
|
+
},
|
|
422
|
+
name: agentTool.name,
|
|
423
|
+
parameters: agentTool.parameters
|
|
424
|
+
}));
|
|
425
|
+
tools.push(rawTool({
|
|
426
|
+
description: "Submit all findings and finish the review. Submit an empty findings array when there are no issues.",
|
|
427
|
+
execute: async (input) => {
|
|
428
|
+
report = parse(declarativeFindingResponseSchema, input);
|
|
429
|
+
return report;
|
|
430
|
+
},
|
|
431
|
+
name: reportFindingsToolName,
|
|
432
|
+
parameters: toolParametersFromSchema(declarativeFindingResponseSchema),
|
|
433
|
+
strict: true
|
|
434
|
+
}));
|
|
435
|
+
const result = await runner({
|
|
436
|
+
channel: {
|
|
437
|
+
emit: () => {},
|
|
438
|
+
subscribe: () => () => {}
|
|
439
|
+
},
|
|
440
|
+
input: [user([
|
|
441
|
+
formatOutputLanguageInstruction(options.outputLanguage),
|
|
442
|
+
`Project root: ${options.cwd}`,
|
|
443
|
+
`Reviewed target file path: ${options.targetFilePath}`,
|
|
444
|
+
`Reviewed target source with line numbers:\n\n${formatSourceWithLineNumbers(options.sourceText)}`
|
|
445
|
+
].filter(Boolean).join("\n\n"))],
|
|
446
|
+
instructions: [
|
|
447
|
+
options.instruction,
|
|
448
|
+
"Use the filesystem tools to inspect the project as needed before reaching a conclusion.",
|
|
449
|
+
`When the review is complete, call ${reportFindingsToolName} exactly once with all findings. Submit an empty findings array when there are no issues.`
|
|
450
|
+
].join("\n\n"),
|
|
451
|
+
tools,
|
|
452
|
+
turnId: "alint"
|
|
453
|
+
});
|
|
454
|
+
if (!report) throw new Error(`basic-coding-agent stopped without calling ${reportFindingsToolName}`);
|
|
455
|
+
return {
|
|
456
|
+
findings: report.findings,
|
|
457
|
+
usage: result.usage ? {
|
|
458
|
+
inputTokens: result.usage.inputTokens,
|
|
459
|
+
outputTokens: result.usage.outputTokens,
|
|
460
|
+
totalTokens: result.usage.totalTokens
|
|
461
|
+
} : void 0
|
|
462
|
+
};
|
|
463
|
+
} };
|
|
464
|
+
}
|
|
465
|
+
//#endregion
|
|
466
|
+
//#region src/plugins/declarative/plugin.ts
|
|
467
|
+
function createDeclarativePlugin(options) {
|
|
468
|
+
return { rules: Object.fromEntries(options.rules.map((rule) => [rule.name, createDeclarativeRule(rule)])) };
|
|
469
|
+
}
|
|
470
|
+
function createDeclarativeRule(rule) {
|
|
471
|
+
if (rule.builtInAgent === "basic-coding-agent") return createBasicCodingAgentRule(rule);
|
|
472
|
+
return createBasicStructuredRule(rule);
|
|
473
|
+
}
|
|
474
|
+
//#endregion
|
|
91
475
|
//#region src/plugins/sources/manifest.ts
|
|
92
476
|
function resolveRelativeRootEntry(packageJson) {
|
|
93
477
|
const [entry] = exports(packageJson, ".", {
|
|
@@ -114,7 +498,7 @@ async function createLockEntry$1(installed, options) {
|
|
|
114
498
|
}
|
|
115
499
|
async function install$1(options) {
|
|
116
500
|
const packageDir = await canonicalRoot(options.alias, options.specifier.directory);
|
|
117
|
-
await
|
|
501
|
+
await validateInstallRoot(options.alias, packageDir);
|
|
118
502
|
return {
|
|
119
503
|
path: packageDir,
|
|
120
504
|
type: "directory"
|
|
@@ -124,10 +508,7 @@ async function resolve$2(entry) {
|
|
|
124
508
|
const lockedPath = isAbsolute(entry.lockEntry.path) || win32.isAbsolute(entry.lockEntry.path) ? entry.lockEntry.path : resolve(entry.cwd, entry.lockEntry.path);
|
|
125
509
|
const [packageDir, lockedPackageDir] = await Promise.all([lockedRoot(entry.alias, entry.specifier.directory, "configured"), lockedRoot(entry.alias, lockedPath, "locked")]);
|
|
126
510
|
if (packageDir !== lockedPackageDir) throw new Error(`Directory plugin "${entry.alias}" has moved or its symlink target changed. Run: alint plugin install`);
|
|
127
|
-
return
|
|
128
|
-
cache: "content",
|
|
129
|
-
entry: await validateRoot(entry.alias, packageDir)
|
|
130
|
-
};
|
|
511
|
+
return validateResolvedRoot(entry.alias, packageDir);
|
|
131
512
|
}
|
|
132
513
|
async function canonicalRoot(alias, directory) {
|
|
133
514
|
let packageDir;
|
|
@@ -146,6 +527,15 @@ async function canonicalRoot(alias, directory) {
|
|
|
146
527
|
if (!directoryStat.isDirectory()) throw new Error(`Directory plugin "${alias}" path "${directory}" is not a directory.`);
|
|
147
528
|
return packageDir;
|
|
148
529
|
}
|
|
530
|
+
async function hasPackageJson(packageDir) {
|
|
531
|
+
try {
|
|
532
|
+
await access(join(packageDir, "package.json"));
|
|
533
|
+
return true;
|
|
534
|
+
} catch (error) {
|
|
535
|
+
if (isENOENTError(error)) return false;
|
|
536
|
+
throw error;
|
|
537
|
+
}
|
|
538
|
+
}
|
|
149
539
|
async function lockedRoot(alias, directory, source) {
|
|
150
540
|
try {
|
|
151
541
|
return await realpath(directory);
|
|
@@ -154,7 +544,25 @@ async function lockedRoot(alias, directory, source) {
|
|
|
154
544
|
throw new Error(`Could not resolve ${source} directory plugin "${alias}" at "${directory}".`, { cause: error });
|
|
155
545
|
}
|
|
156
546
|
}
|
|
157
|
-
async function
|
|
547
|
+
async function validateInstallRoot(alias, packageDir) {
|
|
548
|
+
if (await hasPackageJson(packageDir)) return {
|
|
549
|
+
alias,
|
|
550
|
+
cache: "content",
|
|
551
|
+
entry: await validatePackageRoot(alias, packageDir),
|
|
552
|
+
kind: "module"
|
|
553
|
+
};
|
|
554
|
+
await loadDeclarativeRules({
|
|
555
|
+
alias,
|
|
556
|
+
root: packageDir
|
|
557
|
+
});
|
|
558
|
+
return {
|
|
559
|
+
alias,
|
|
560
|
+
cache: "content",
|
|
561
|
+
entry: packageDir,
|
|
562
|
+
kind: "declarative"
|
|
563
|
+
};
|
|
564
|
+
}
|
|
565
|
+
async function validatePackageRoot(alias, packageDir) {
|
|
158
566
|
const manifestPath = join(packageDir, "package.json");
|
|
159
567
|
let packageJson;
|
|
160
568
|
try {
|
|
@@ -183,6 +591,21 @@ async function validateRoot(alias, packageDir) {
|
|
|
183
591
|
if (!entryStat.isFile()) throw new Error(`Directory plugin "${alias}" entry "${relativeEntry}" is not a regular file.`);
|
|
184
592
|
return physicalEntry;
|
|
185
593
|
}
|
|
594
|
+
async function validateResolvedRoot(alias, packageDir) {
|
|
595
|
+
if (await hasPackageJson(packageDir)) return {
|
|
596
|
+
alias,
|
|
597
|
+
cache: "content",
|
|
598
|
+
entry: await validatePackageRoot(alias, packageDir),
|
|
599
|
+
kind: "module"
|
|
600
|
+
};
|
|
601
|
+
if (!await hasDeclarativeRuleFiles(packageDir)) throw new Error(`Directory plugin "${alias}" must contain package.json or rule.alint.* files.`);
|
|
602
|
+
return {
|
|
603
|
+
alias,
|
|
604
|
+
cache: "content",
|
|
605
|
+
entry: packageDir,
|
|
606
|
+
kind: "declarative"
|
|
607
|
+
};
|
|
608
|
+
}
|
|
186
609
|
//#endregion
|
|
187
610
|
//#region src/plugins/sources/package/index.ts
|
|
188
611
|
function createLockEntry(installed, options) {
|
|
@@ -246,8 +669,10 @@ async function resolve$1(entry) {
|
|
|
246
669
|
if (!isPathInside(resolvedEntry, packageDir)) throw new Error(`Plugin lock entry "${entry.alias}" resolves outside the locked package directory.`);
|
|
247
670
|
JSON.parse(await readFile(join(packageDir, "package.json"), "utf8"));
|
|
248
671
|
return {
|
|
672
|
+
alias: entry.alias,
|
|
249
673
|
cache: "default",
|
|
250
|
-
entry: resolvedEntry
|
|
674
|
+
entry: resolvedEntry,
|
|
675
|
+
kind: "module"
|
|
251
676
|
};
|
|
252
677
|
}
|
|
253
678
|
async function extractEntry(packageDir, header, stream) {
|
|
@@ -563,6 +988,10 @@ function resolveDirectoryLockIdentity(path, cwd) {
|
|
|
563
988
|
//#endregion
|
|
564
989
|
//#region src/plugins/sources/import.ts
|
|
565
990
|
async function importPlugin(target) {
|
|
991
|
+
if (target.kind === "declarative") return createDeclarativePlugin({ rules: await loadDeclarativeRules({
|
|
992
|
+
alias: target.alias,
|
|
993
|
+
root: target.entry
|
|
994
|
+
}) });
|
|
566
995
|
const url = pathToFileURL(target.entry);
|
|
567
996
|
if (target.cache === "content") url.searchParams.set("content", createHash("sha256").update(await readFile(target.entry)).digest("hex"));
|
|
568
997
|
return getDefaultExport(await import(url.href));
|
|
@@ -584,6 +1013,7 @@ const ruleConfigEntrySchema = union([ruleSeveritySchema, tuple([ruleSeveritySche
|
|
|
584
1013
|
const staticConfigItemSchema = looseObject({
|
|
585
1014
|
agent: optional(unknown()),
|
|
586
1015
|
basePath: optional(string()),
|
|
1016
|
+
directories: optional(array(filePatternSchema)),
|
|
587
1017
|
extends: optional(array(unknown())),
|
|
588
1018
|
files: optional(array(filePatternSchema)),
|
|
589
1019
|
ignore: optional(looseObject({ gitignore: optional(boolean()) })),
|
|
@@ -1094,4 +1524,4 @@ async function writeSetupConfig(filePath, config) {
|
|
|
1094
1524
|
await writeFile(filePath, stringifySetupConfigToml(config), "utf8");
|
|
1095
1525
|
}
|
|
1096
1526
|
//#endregion
|
|
1097
|
-
export { createEmptyPluginLockFile, emptySetupConfig, getGlobalSetupConfigPath, getProjectPluginLockPath, getProjectPluginStorePath, getProjectSetupConfigPath, getStatsDir, ignorePatternsAIAgents, ignorePatternsBuildOutputs, ignorePatternsCaches, ignorePatternsCommon, ignorePatternsEslintDefaults, ignorePatternsGenerated, installStaticPlugins, listMissing, listUnresolved, loadAlintConfig, loadPluginLockFile, loadSetupConfig, loadStaticConfig, mergeSetupConfigs, parsePluginLockFile, parsePluginSpecifier, parseSetupConfigToml, parseStaticConfig, stringifySetupConfigToml, toAlintConfig, writePluginLockFile, writeSetupConfig };
|
|
1527
|
+
export { builtInAgentNames, createDeclarativePlugin, createEmptyPluginLockFile, createReportScope, declarativeFindingResponseSchema, declarativeFindingSchema, declarativeRuleFilePattern, emptySetupConfig, getGlobalSetupConfigPath, getProjectPluginLockPath, getProjectPluginStorePath, getProjectSetupConfigPath, getStatsDir, hasDeclarativeRuleFiles, ignorePatternsAIAgents, ignorePatternsBuildOutputs, ignorePatternsCaches, ignorePatternsCommon, ignorePatternsEslintDefaults, ignorePatternsGenerated, installStaticPlugins, isBuiltInAgentName, listMissing, listUnresolved, loadAlintConfig, loadDeclarativeRules, loadPluginLockFile, loadSetupConfig, loadStaticConfig, mergeSetupConfigs, parsePluginLockFile, parsePluginSpecifier, parseSetupConfigToml, parseStaticConfig, stringifySetupConfigToml, toAlintConfig, writePluginLockFile, writeSetupConfig };
|
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@alint-js/config",
|
|
3
3
|
"type": "module",
|
|
4
|
-
"version": "0.0.
|
|
4
|
+
"version": "0.0.23",
|
|
5
5
|
"exports": {
|
|
6
6
|
".": {
|
|
7
7
|
"types": "./dist/index.d.mts",
|
|
@@ -15,9 +15,11 @@
|
|
|
15
15
|
"dependencies": {
|
|
16
16
|
"@moeru/std": "^0.1.0-beta.18",
|
|
17
17
|
"@package-json/types": "^0.0.13",
|
|
18
|
+
"apeira": "^0.0.7",
|
|
18
19
|
"c12": "^3.3.4",
|
|
19
20
|
"es-toolkit": "^1.49.0",
|
|
20
21
|
"jiti": "^2.7.0",
|
|
22
|
+
"minimatch": "^10.2.5",
|
|
21
23
|
"ofetch": "^1.5.1",
|
|
22
24
|
"pathe": "^2.0.3",
|
|
23
25
|
"resolve.exports": "2.0.3",
|
|
@@ -25,15 +27,12 @@
|
|
|
25
27
|
"tar-stream": "^3.2.0",
|
|
26
28
|
"valibot": "^1.4.1",
|
|
27
29
|
"xdg-basedir": "^5.1.0",
|
|
28
|
-
"@alint-js/core": "0.0.
|
|
30
|
+
"@alint-js/core": "0.0.23",
|
|
31
|
+
"@alint-js/tools-fs": "0.0.23"
|
|
29
32
|
},
|
|
30
33
|
"devDependencies": {
|
|
31
|
-
"@types/node": "^26.0.1",
|
|
32
34
|
"@types/tar-stream": "^3.1.4",
|
|
33
|
-
"h3": "2.0.1-rc.25"
|
|
34
|
-
"tsdown": "^0.22.3",
|
|
35
|
-
"typescript": "^6.0.3",
|
|
36
|
-
"vitest": "^4.1.9"
|
|
35
|
+
"h3": "2.0.1-rc.25"
|
|
37
36
|
},
|
|
38
37
|
"scripts": {
|
|
39
38
|
"build": "tsdown",
|