@visulima/vis 1.0.0-alpha.11 → 1.0.0-alpha.13

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.
Files changed (116) hide show
  1. package/CHANGELOG.md +101 -0
  2. package/LICENSE.md +559 -186
  3. package/README.md +18 -0
  4. package/dist/bin.js +1 -9
  5. package/dist/config/index.d.ts +477 -556
  6. package/dist/config/index.js +1 -2
  7. package/dist/generate/index.js +1 -3
  8. package/dist/packem_chunks/applyDefaults.js +2 -336
  9. package/dist/packem_chunks/bin.js +234 -9552
  10. package/dist/packem_chunks/doctor-probe.js +2 -112
  11. package/dist/packem_chunks/fix.js +11 -234
  12. package/dist/packem_chunks/handler.js +1 -99
  13. package/dist/packem_chunks/handler10.js +2 -53
  14. package/dist/packem_chunks/handler11.js +1 -32
  15. package/dist/packem_chunks/handler12.js +5 -100
  16. package/dist/packem_chunks/handler13.js +1 -25
  17. package/dist/packem_chunks/handler14.js +18 -916
  18. package/dist/packem_chunks/handler15.js +15 -201
  19. package/dist/packem_chunks/handler16.js +1 -124
  20. package/dist/packem_chunks/handler17.js +1 -13
  21. package/dist/packem_chunks/handler18.js +1 -106
  22. package/dist/packem_chunks/handler19.js +1 -19
  23. package/dist/packem_chunks/handler2.js +2 -75
  24. package/dist/packem_chunks/handler20.js +5 -29
  25. package/dist/packem_chunks/handler21.js +1 -222
  26. package/dist/packem_chunks/handler22.js +1 -237
  27. package/dist/packem_chunks/handler23.js +5 -101
  28. package/dist/packem_chunks/handler24.js +1 -110
  29. package/dist/packem_chunks/handler25.js +3 -402
  30. package/dist/packem_chunks/handler26.js +1 -13
  31. package/dist/packem_chunks/handler27.js +1 -63
  32. package/dist/packem_chunks/handler28.js +7 -34
  33. package/dist/packem_chunks/handler29.js +21 -456
  34. package/dist/packem_chunks/handler3.js +4 -95
  35. package/dist/packem_chunks/handler30.js +3 -170
  36. package/dist/packem_chunks/handler31.js +1 -530
  37. package/dist/packem_chunks/handler32.js +2 -214
  38. package/dist/packem_chunks/handler33.js +25 -119
  39. package/dist/packem_chunks/handler34.js +2 -630
  40. package/dist/packem_chunks/handler35.js +3 -283
  41. package/dist/packem_chunks/handler36.js +22 -542
  42. package/dist/packem_chunks/handler37.js +410 -744
  43. package/dist/packem_chunks/handler38.js +22 -989
  44. package/dist/packem_chunks/handler39.js +22 -574
  45. package/dist/packem_chunks/handler4.js +2 -90
  46. package/dist/packem_chunks/handler40.js +22 -1685
  47. package/dist/packem_chunks/handler41.js +6 -1088
  48. package/dist/packem_chunks/handler42.js +5 -797
  49. package/dist/packem_chunks/handler43.js +10 -2658
  50. package/dist/packem_chunks/handler44.js +51 -3784
  51. package/dist/packem_chunks/handler45.js +25 -2574
  52. package/dist/packem_chunks/handler46.js +3 -3769
  53. package/dist/packem_chunks/handler47.js +21 -1485
  54. package/dist/packem_chunks/handler48.js +42 -0
  55. package/dist/packem_chunks/handler5.js +8 -174
  56. package/dist/packem_chunks/handler6.js +1 -95
  57. package/dist/packem_chunks/handler7.js +1 -115
  58. package/dist/packem_chunks/handler8.js +1 -12
  59. package/dist/packem_chunks/handler9.js +1 -29
  60. package/dist/packem_chunks/heal-accept.js +10 -522
  61. package/dist/packem_chunks/heal.js +14 -673
  62. package/dist/packem_chunks/index.js +7 -873
  63. package/dist/packem_chunks/loader.js +1 -23
  64. package/dist/packem_chunks/tar.js +3 -0
  65. package/dist/packem_shared/ai-analysis-hm8d2W7z.js +67 -0
  66. package/dist/packem_shared/ai-cache-DoiF80AR.js +1 -0
  67. package/dist/packem_shared/ai-fix-nn4zOE95.js +43 -0
  68. package/dist/packem_shared/cache-directory-CwHlJhgx.js +1 -0
  69. package/dist/packem_shared/dependency-scan-COr5n63B.js +2 -0
  70. package/dist/packem_shared/docker-D6OGr5_S.js +2 -0
  71. package/dist/packem_shared/failure-log-iUVLf6ts.js +2 -0
  72. package/dist/packem_shared/flakiness-D9wf0t56.js +1 -0
  73. package/dist/packem_shared/giget-CcEy_Elm.js +2 -0
  74. package/dist/packem_shared/index-DH-5hsrC.js +1 -0
  75. package/dist/packem_shared/otel-DxDUPJJH.js +6 -0
  76. package/dist/packem_shared/otelPlugin-CQq6poq8.js +1 -0
  77. package/dist/packem_shared/registry-CkubDdiY.js +2 -0
  78. package/dist/packem_shared/run-summary-utils-BfBvjzhY.js +1 -0
  79. package/dist/packem_shared/runtime-check-BXZ43CBW.js +1 -0
  80. package/dist/packem_shared/selectors-BylODRiM.js +3 -0
  81. package/dist/packem_shared/symbols-CQmER5MT.js +1 -0
  82. package/dist/packem_shared/toolchain-BgBOUHII.js +5 -0
  83. package/dist/packem_shared/typosquats-CcZl99B1.js +1 -0
  84. package/dist/packem_shared/use-measured-height-DjYgUOKk.js +1 -0
  85. package/dist/packem_shared/utils-DrNg0XTR.js +1 -0
  86. package/dist/packem_shared/verify-Baj5mFJ7.js +1 -0
  87. package/dist/packem_shared/vis-update-app-D1jl0UZZ.js +1 -0
  88. package/dist/packem_shared/xxh3-DrAUNq4n.js +1 -0
  89. package/index.js +556 -727
  90. package/package.json +19 -29
  91. package/schemas/project.schema.json +739 -297
  92. package/schemas/vis-config.schema.json +3365 -384
  93. package/templates/buildkite-ci/template.yml +20 -20
  94. package/dist/packem_shared/VisUpdateApp-D-Yz_wvg.js +0 -1316
  95. package/dist/packem_shared/_commonjsHelpers-BqLXS_qQ.js +0 -5
  96. package/dist/packem_shared/ai-analysis-CHeB1joD.js +0 -367
  97. package/dist/packem_shared/ai-cache-Be_jexe4.js +0 -142
  98. package/dist/packem_shared/ai-fix-B9iQVcD2.js +0 -379
  99. package/dist/packem_shared/cache-directory-2qvs4goY.js +0 -98
  100. package/dist/packem_shared/catalog-BJTtyi-O.js +0 -1371
  101. package/dist/packem_shared/dependency-scan-A0KSklpG.js +0 -188
  102. package/dist/packem_shared/docker-2iZzc280.js +0 -181
  103. package/dist/packem_shared/failure-log-Cz3Z4SKL.js +0 -100
  104. package/dist/packem_shared/flakiness-goTxXuCX.js +0 -180
  105. package/dist/packem_shared/otel-DCvqCTz_.js +0 -158
  106. package/dist/packem_shared/otelPlugin-DFaLDvJf.js +0 -3
  107. package/dist/packem_shared/registry-CbqXI0rc.js +0 -272
  108. package/dist/packem_shared/run-summary-utils-PVMl4aIh.js +0 -130
  109. package/dist/packem_shared/runtime-check-Cobi3p6l.js +0 -127
  110. package/dist/packem_shared/selectors-SM69TfqC.js +0 -194
  111. package/dist/packem_shared/symbols-Ta7g2nU-.js +0 -14
  112. package/dist/packem_shared/toolchain-BdZd9eBi.js +0 -975
  113. package/dist/packem_shared/typosquats-C-bCh3PX.js +0 -1210
  114. package/dist/packem_shared/use-measured-height-CNP0vT4M.js +0 -20
  115. package/dist/packem_shared/utils-CthVdBPS.js +0 -40
  116. package/dist/packem_shared/xxh3-Ck8mXNg1.js +0 -239
@@ -1,5 +0,0 @@
1
- function getDefaultExportFromCjs(x) {
2
- return x && x.__esModule && Object.prototype.hasOwnProperty.call(x, "default") ? x["default"] : x;
3
- }
4
-
5
- export { getDefaultExportFromCjs as g };
@@ -1,367 +0,0 @@
1
- import { runProvider, PROVIDER_NAMES, detectProvider, detectAvailableProviders } from '@visulima/find-ai-runner';
2
- import { renderToString, Box, Text, Table } from '@visulima/tui';
3
- import React from 'react';
4
- import { b as buildCacheKey, a as getCachedAnalysis, s as setCachedAnalysis, d as getTtlForAnalysisType } from './ai-cache-Be_jexe4.js';
5
-
6
- const AI_TIMEOUT_MS = 12e4;
7
- const MAX_RETRIES = 2;
8
- const RETRY_BASE_DELAY_MS = 1e3;
9
- const sleep = (ms) => new Promise((resolve) => {
10
- setTimeout(resolve, ms);
11
- });
12
- const runWithRetry = async (provider, prompt, retries = MAX_RETRIES) => {
13
- let lastError;
14
- for (let attempt = 0; attempt <= retries; attempt += 1) {
15
- try {
16
- const result = await runProvider(provider, prompt, { timeoutMs: AI_TIMEOUT_MS });
17
- return result.stdout;
18
- } catch (error) {
19
- lastError = error instanceof Error ? error : new Error(String(error));
20
- if (lastError.message.includes("timed out")) {
21
- throw lastError;
22
- }
23
- if (attempt < retries) {
24
- const delay = RETRY_BASE_DELAY_MS * 2 ** attempt;
25
- await sleep(delay);
26
- }
27
- }
28
- }
29
- throw lastError ?? new Error("AI request failed after retries");
30
- };
31
-
32
- const DEFAULT_PRIORITY = {
33
- amp: 30,
34
- claude: 80,
35
- codex: 60,
36
- copilot: 50,
37
- crush: 35,
38
- cursor: 40,
39
- droid: 20,
40
- gemini: 100,
41
- kimi: 25,
42
- opencode: 35,
43
- qwen: 30
44
- };
45
- const resolveProvider = (config) => {
46
- if (config?.provider) {
47
- if (!PROVIDER_NAMES.includes(config.provider)) {
48
- return void 0;
49
- }
50
- const provider = detectProvider(config.provider);
51
- return provider.available ? provider : void 0;
52
- }
53
- const available = detectAvailableProviders();
54
- if (available.length === 0) {
55
- return void 0;
56
- }
57
- const priority = { ...DEFAULT_PRIORITY, ...config?.priority };
58
- return available.toSorted((a, b) => (priority[b.name] ?? 0) - (priority[a.name] ?? 0))[0];
59
- };
60
- const VALID_ACTIONS = /* @__PURE__ */ new Set(["defer", "review", "skip", "update"]);
61
- const VALID_RISK_LEVELS = /* @__PURE__ */ new Set(["critical", "high", "low", "medium"]);
62
- const VALID_EFFORTS = /* @__PURE__ */ new Set(["high", "low", "medium"]);
63
- const CHUNK_THRESHOLD = 50;
64
- const CHUNK_SIZE = 30;
65
- const buildPackageList = (outdated) => outdated.map((entry) => {
66
- const vulnInfo = entry.vulnerabilities && entry.vulnerabilities.length > 0 ? ` [VULNERABILITIES: ${entry.vulnerabilities.map((v) => `${v.severity} ${v.id}`).join(", ")}]` : "";
67
- let socketInfo = "";
68
- if (entry.socketReport) {
69
- const score = Math.round(entry.socketReport.score.overall * 100);
70
- const parts = [`score:${String(score)}%`];
71
- if (entry.socketReport.alerts.length > 0) {
72
- const alertsByLevel = entry.socketReport.alerts.reduce((accumulator, a) => {
73
- accumulator[a.severity] = (accumulator[a.severity] ?? 0) + 1;
74
- return accumulator;
75
- }, {});
76
- const alertSummary = Object.entries(alertsByLevel).map(([s, c]) => `${String(c)} ${s}`).join(", ");
77
- parts.push(`alerts: ${alertSummary}`);
78
- }
79
- parts.push(`supply-chain:${String(Math.round(entry.socketReport.score.supplyChain * 100))}%`);
80
- parts.push(`quality:${String(Math.round(entry.socketReport.score.quality * 100))}%`);
81
- socketInfo = ` [SOCKET.DEV: ${parts.join(", ")}]`;
82
- }
83
- return `- ${entry.packageName}: ${entry.currentRange} → ${entry.newRange} (${entry.updateType})${vulnInfo}${socketInfo}`;
84
- }).join("\n");
85
- const JSON_RESPONSE_SCHEMA = `Respond ONLY with valid JSON in this exact structure:
86
- {
87
- "summary": "Brief overall summary",
88
- "recommendations": [
89
- {
90
- "package": "package-name",
91
- "action": "update|skip|review|defer",
92
- "reason": "explanation",
93
- "riskLevel": "low|medium|high|critical",
94
- "breakingChanges": ["change1"],
95
- "effort": "low|medium|high"
96
- }
97
- ],
98
- "warnings": ["warning1"]
99
- }`;
100
- const PROMPTS = {
101
- compatibility: (packageList) => `Analyze the compatibility of these package updates:
102
-
103
- ${packageList}
104
-
105
- For each package:
106
- 1. Check peer dependency compatibility
107
- 2. Identify potential conflicts with other packages in the list
108
- 3. Assess API compatibility between current and target versions
109
- 4. Check for deprecated features being removed
110
- 5. Evaluate Node.js version requirements
111
-
112
- ${JSON_RESPONSE_SCHEMA}`,
113
- impact: (packageList) => `Analyze the impact of updating these npm packages:
114
-
115
- ${packageList}
116
-
117
- For each package, provide:
118
- 1. Risk level (low/medium/high/critical)
119
- 2. Recommended action (update/skip/review/defer)
120
- 3. Reason for recommendation
121
- 4. Known breaking changes (if any)
122
- 5. Estimated migration effort (low/medium/high)
123
-
124
- ${JSON_RESPONSE_SCHEMA}`,
125
- recommend: (packageList) => `Provide smart recommendations for updating these packages:
126
-
127
- ${packageList}
128
-
129
- Consider:
130
- 1. Update priority based on security, features, and stability
131
- 2. Grouping related packages for atomic updates
132
- 3. Best practices for the specific package ecosystem
133
- 4. Risk vs. benefit analysis
134
- 5. Suggested update order
135
- 6. If Socket.dev scores are provided, prioritize packages with low supply chain or quality scores
136
-
137
- ${JSON_RESPONSE_SCHEMA}`,
138
- security: (packageList) => `Analyze the security implications of these package updates:
139
-
140
- ${packageList}
141
-
142
- For each package:
143
- 1. Check if the update fixes known vulnerabilities (use the vulnerability data above)
144
- 2. Assess if the new version introduces security risks
145
- 3. Evaluate if this is a security-sensitive package (auth, crypto, session, etc.)
146
- 4. Recommend urgency of the update based on vulnerability severity
147
- 5. Flag any packages where skipping the update poses security risk
148
- 6. If Socket.dev scores are provided, factor in supply chain and quality scores — low scores indicate higher risk
149
-
150
- ${JSON_RESPONSE_SCHEMA}`
151
- };
152
- const VALID_ANALYSIS_TYPES = /* @__PURE__ */ new Set(["compatibility", "impact", "recommend", "security"]);
153
- const validateAnalysisType = (type) => {
154
- if (VALID_ANALYSIS_TYPES.has(type)) {
155
- return type;
156
- }
157
- return "impact";
158
- };
159
- const buildAnalysisPrompt = (outdated, analysisType = "impact") => {
160
- const packageList = buildPackageList(outdated);
161
- return PROMPTS[analysisType](packageList);
162
- };
163
- const JSON_BLOCK_REGEX = /```(?:json)?\s*([\s\S]*?)```/;
164
- const JSON_OBJECT_REGEX = /\{[\s\S]*\}/;
165
- const extractJson = (text) => {
166
- try {
167
- return JSON.parse(text);
168
- } catch {
169
- }
170
- const blockMatch = JSON_BLOCK_REGEX.exec(text);
171
- if (blockMatch?.[1]) {
172
- try {
173
- return JSON.parse(blockMatch[1]);
174
- } catch {
175
- }
176
- }
177
- const objectMatch = JSON_OBJECT_REGEX.exec(text);
178
- if (objectMatch?.[0]) {
179
- try {
180
- return JSON.parse(objectMatch[0]);
181
- } catch {
182
- }
183
- }
184
- return void 0;
185
- };
186
- const normalizeRecommendation = (raw) => {
187
- return {
188
- action: VALID_ACTIONS.has(raw.action) ? raw.action : "review",
189
- breakingChanges: Array.isArray(raw.breakingChanges) ? raw.breakingChanges : [],
190
- effort: VALID_EFFORTS.has(raw.effort) ? raw.effort : "medium",
191
- package: typeof raw.package === "string" ? raw.package : "",
192
- reason: typeof raw.reason === "string" ? raw.reason : "",
193
- riskLevel: VALID_RISK_LEVELS.has(raw.riskLevel) ? raw.riskLevel : "medium"
194
- };
195
- };
196
- const parseAiResponse = (text, provider, analysisType) => {
197
- const parsed = extractJson(text);
198
- if (!parsed || typeof parsed !== "object") {
199
- return { analysisType, provider, recommendations: [], summary: "Failed to parse AI response.", warnings: ["AI response was not valid JSON."] };
200
- }
201
- const data = parsed;
202
- const rawRecs = Array.isArray(data.recommendations) ? data.recommendations : [];
203
- return {
204
- analysisType,
205
- provider,
206
- recommendations: rawRecs.map((rec) => normalizeRecommendation(rec)),
207
- summary: typeof data.summary === "string" ? data.summary : "",
208
- warnings: Array.isArray(data.warnings) ? data.warnings : []
209
- };
210
- };
211
- const KNOWN_BREAKING = {
212
- eslint: ["ESLint 9.0: Flat config required", "ESLint 8.0+: New rule formats"],
213
- next: ["Next.js 13+: App router changes", "Next.js 14+: Server components default"],
214
- react: ["React 17 to 18: Concurrent features", "React 18+: Strict mode changes"],
215
- typescript: ["TypeScript 5.0: New decorators", "TypeScript 4.7+: ESM changes"],
216
- vite: ["Vite 5: Node.js 18+ required"],
217
- vue: ["Vue 3: Composition API", "Vue 3: Breaking template changes"],
218
- webpack: ["Webpack 5: Node.js polyfills removed"]
219
- };
220
- const SECURITY_SENSITIVE = /* @__PURE__ */ new Set(["bcrypt", "cors", "crypto-js", "express-session", "helmet", "jose", "jsonwebtoken", "node-forge", "oauth", "passport"]);
221
- const ruleBasedAnalysis = (outdated, analysisType) => {
222
- const recommendations = outdated.map((entry) => {
223
- const hasVulnerabilities = entry.vulnerabilities && entry.vulnerabilities.length > 0;
224
- const isSecuritySensitive = SECURITY_SENSITIVE.has(entry.packageName);
225
- const breakingChanges = KNOWN_BREAKING[entry.packageName] ?? [];
226
- let riskLevel = "low";
227
- let action = "update";
228
- let effort = "low";
229
- let reason = "Patch/minor update, safe to apply.";
230
- if (entry.updateType === "major") {
231
- riskLevel = "high";
232
- action = breakingChanges.length > 0 ? "review" : "update";
233
- effort = "medium";
234
- reason = breakingChanges.length > 0 ? `Major update with known breaking changes: ${breakingChanges[0]}` : "Major version update, review changelog before applying.";
235
- } else if (entry.updateType === "minor") {
236
- riskLevel = "medium";
237
- reason = "Minor update, generally safe.";
238
- }
239
- if (hasVulnerabilities) {
240
- riskLevel = "high";
241
- action = "update";
242
- reason = "Security update — current version has known vulnerabilities.";
243
- }
244
- if (isSecuritySensitive && entry.updateType === "major") {
245
- action = "review";
246
- reason = "Security-sensitive package with major update, careful review needed.";
247
- effort = "high";
248
- }
249
- return { action, breakingChanges, effort, package: entry.packageName, reason, riskLevel };
250
- });
251
- return {
252
- analysisType,
253
- provider: "rule-engine",
254
- recommendations,
255
- summary: `Rule-based ${analysisType} analysis for ${String(outdated.length)} packages.`,
256
- warnings: ["No AI provider available — using built-in rule engine."]
257
- };
258
- };
259
- const analyzeChunk = async (provider, chunk, analysisType) => {
260
- const prompt = buildAnalysisPrompt(chunk, analysisType);
261
- const stdout = await runWithRetry(provider, prompt);
262
- return parseAiResponse(stdout, provider.name, analysisType);
263
- };
264
- const mergeResults = (results, provider, analysisType) => {
265
- const recommendations = [];
266
- const warnings = [];
267
- const summaries = [];
268
- for (const result of results) {
269
- recommendations.push(...result.recommendations);
270
- warnings.push(...result.warnings);
271
- if (result.summary) {
272
- summaries.push(result.summary);
273
- }
274
- }
275
- return {
276
- analysisType,
277
- provider,
278
- recommendations,
279
- summary: summaries.length === 1 ? summaries[0] ?? "" : `Analyzed ${String(recommendations.length)} packages in ${String(results.length)} batches.`,
280
- warnings: [...new Set(warnings)]
281
- };
282
- };
283
- const ANALYSIS_TYPE_LABELS = {
284
- compatibility: "Compatibility",
285
- impact: "Impact",
286
- recommend: "Recommendations",
287
- security: "Security"
288
- };
289
- const formatAiAnalysis = (result) => {
290
- const typeLabel = ANALYSIS_TYPE_LABELS[result.analysisType] ?? result.analysisType;
291
- const header = `${typeLabel} Analysis (${result.provider})`;
292
- const tableData = result.recommendations.flatMap((rec) => {
293
- const rows = [
294
- { action: rec.action, effort: rec.effort, package: rec.package, reason: rec.reason, risk: rec.riskLevel }
295
- ];
296
- if (rec.breakingChanges.length > 0) {
297
- rows.push({ action: "", effort: "", package: "", reason: `Breaking: ${rec.breakingChanges.join("; ")}`, risk: "" });
298
- }
299
- return rows;
300
- });
301
- const columns = process.stdout.columns || 80;
302
- return renderToString(
303
- React.createElement(
304
- Box,
305
- { borderStyle: "round", flexDirection: "column", paddingLeft: 1, paddingRight: 1 },
306
- React.createElement(Text, { bold: true }, header),
307
- React.createElement(Text, null, ""),
308
- React.createElement(Text, null, result.summary),
309
- React.createElement(Text, null, ""),
310
- React.createElement(Table, { borderStyle: "none", data: tableData }),
311
- ...result.warnings.length > 0 ? [
312
- React.createElement(Text, null, ""),
313
- ...result.warnings.map((warning, i) => React.createElement(Text, { dimColor: true, key: String(i) }, ` ${warning}`))
314
- ] : []
315
- ),
316
- { columns }
317
- );
318
- };
319
- const runAiAnalysis = async (outdated, logger, config, analysisType = "impact") => {
320
- const provider = resolveProvider(config);
321
- if (!provider) {
322
- logger.info("No AI CLI tool found, using rule-based analysis.\n");
323
- return ruleBasedAnalysis(outdated, analysisType);
324
- }
325
- const cacheKey = buildCacheKey(provider.name, analysisType, outdated);
326
- const cached = getCachedAnalysis(cacheKey);
327
- if (cached) {
328
- logger.info(`Using cached ${analysisType} analysis from ${cached.provider}.
329
- `);
330
- return cached;
331
- }
332
- const typeLabel = ANALYSIS_TYPE_LABELS[analysisType] ?? analysisType;
333
- logger.info(`Running ${typeLabel.toLowerCase()} analysis with ${provider.name}...
334
- `);
335
- try {
336
- let result;
337
- if (outdated.length > CHUNK_THRESHOLD) {
338
- logger.info(`Splitting ${String(outdated.length)} packages into batches of ${String(CHUNK_SIZE)}...
339
- `);
340
- const chunks = [];
341
- for (let index = 0; index < outdated.length; index += CHUNK_SIZE) {
342
- chunks.push(outdated.slice(index, index + CHUNK_SIZE));
343
- }
344
- const results = [];
345
- for (let index = 0; index < chunks.length; index += 1) {
346
- logger.info(` Batch ${String(index + 1)}/${String(chunks.length)}...`);
347
- const chunk = chunks[index];
348
- if (chunk) {
349
- results.push(await analyzeChunk(provider, chunk, analysisType));
350
- }
351
- }
352
- result = mergeResults(results, provider.name, analysisType);
353
- } else {
354
- const stdout = await runWithRetry(provider, buildAnalysisPrompt(outdated, analysisType));
355
- result = parseAiResponse(stdout, provider.name, analysisType);
356
- }
357
- setCachedAnalysis(cacheKey, result, getTtlForAnalysisType(analysisType, config?.cacheTtl));
358
- return result;
359
- } catch (error) {
360
- const message = error instanceof Error ? error.message : String(error);
361
- logger.warn(`AI analysis failed (${message}), falling back to rule engine.
362
- `);
363
- return ruleBasedAnalysis(outdated, analysisType);
364
- }
365
- };
366
-
367
- export { DEFAULT_PRIORITY as D, resolveProvider as a, runWithRetry as b, extractJson as e, formatAiAnalysis as f, runAiAnalysis as r, validateAnalysisType as v };
@@ -1,142 +0,0 @@
1
- import { createRequire as __cjs_createRequire } from "node:module";
2
-
3
- const __cjs_require = __cjs_createRequire(import.meta.url);
4
-
5
- const __cjs_getProcess = typeof globalThis !== "undefined" && typeof globalThis.process !== "undefined" ? globalThis.process : process;
6
-
7
- const __cjs_getBuiltinModule = (module) => {
8
- // Check if we're in Node.js and version supports getBuiltinModule
9
- if (typeof __cjs_getProcess !== "undefined" && __cjs_getProcess.versions && __cjs_getProcess.versions.node) {
10
- const [major, minor] = __cjs_getProcess.versions.node.split(".").map(Number);
11
- // Node.js 20.16.0+ and 22.3.0+
12
- if (major > 22 || (major === 22 && minor >= 3) || (major === 20 && minor >= 16)) {
13
- return __cjs_getProcess.getBuiltinModule(module);
14
- }
15
- }
16
- // Fallback to createRequire
17
- return __cjs_require(module);
18
- };
19
-
20
- const {
21
- rmSync,
22
- writeFileSync,
23
- readdirSync,
24
- statSync
25
- } = __cjs_getBuiltinModule("node:fs");
26
- const {
27
- homedir
28
- } = __cjs_getBuiltinModule("node:os");
29
- import { x as xxh3Hash } from './xxh3-Ck8mXNg1.js';
30
- import { isAccessibleSync, readJsonSync, ensureDirSync } from '@visulima/fs';
31
- import { join } from '@visulima/path';
32
-
33
- const getCacheDirectory = () => join(homedir(), ".vis", "cache", "ai");
34
- const DEFAULT_TTL_MS = 60 * 60 * 1e3;
35
- const SECURITY_TTL_MS = 30 * 60 * 1e3;
36
- const ensureCacheDirectory = () => {
37
- ensureDirSync(getCacheDirectory());
38
- };
39
- const buildCacheKey = (provider, analysisType, outdated) => {
40
- const packages = outdated.map((entry) => {
41
- return { currentRange: entry.currentRange, name: entry.packageName, targetVersion: entry.targetVersion };
42
- }).toSorted((a, b) => a.name.localeCompare(b.name));
43
- const payload = JSON.stringify({ analysisType, packages, provider });
44
- return xxh3Hash(Buffer.from(payload));
45
- };
46
- const getCachedAnalysis = (cacheKey) => {
47
- const filePath = join(getCacheDirectory(), `${cacheKey}.json`);
48
- if (!isAccessibleSync(filePath)) {
49
- return void 0;
50
- }
51
- try {
52
- const entry = readJsonSync(filePath);
53
- if (Date.now() - entry.createdAt > entry.ttlMs) {
54
- rmSync(filePath, { force: true });
55
- return void 0;
56
- }
57
- return entry.result;
58
- } catch {
59
- rmSync(filePath, { force: true });
60
- return void 0;
61
- }
62
- };
63
- const setCachedAnalysis = (cacheKey, result, ttlMs) => {
64
- ensureCacheDirectory();
65
- const cacheDirectory = getCacheDirectory();
66
- const entry = {
67
- createdAt: Date.now(),
68
- result,
69
- ttlMs
70
- };
71
- writeFileSync(join(cacheDirectory, `${cacheKey}.json`), JSON.stringify(entry, void 0, 2), "utf8");
72
- };
73
- const getTtlForAnalysisType = (analysisType, configTtl) => {
74
- if (configTtl !== void 0 && configTtl > 0) {
75
- return configTtl;
76
- }
77
- return analysisType === "security" ? SECURITY_TTL_MS : DEFAULT_TTL_MS;
78
- };
79
- const getCacheStats = () => {
80
- const cacheDirectory = getCacheDirectory();
81
- if (!isAccessibleSync(cacheDirectory)) {
82
- return { entries: 0, newestEntry: void 0, oldestEntry: void 0, totalSizeBytes: 0 };
83
- }
84
- const files = readdirSync(cacheDirectory).filter((f) => f.endsWith(".json"));
85
- let totalSizeBytes = 0;
86
- let oldest;
87
- let newest;
88
- for (const file of files) {
89
- const filePath = join(cacheDirectory, file);
90
- const stat = statSync(filePath);
91
- totalSizeBytes += stat.size;
92
- const { mtimeMs } = stat;
93
- if (oldest === void 0 || mtimeMs < oldest) {
94
- oldest = mtimeMs;
95
- }
96
- if (newest === void 0 || mtimeMs > newest) {
97
- newest = mtimeMs;
98
- }
99
- }
100
- return { entries: files.length, newestEntry: newest, oldestEntry: oldest, totalSizeBytes };
101
- };
102
- const buildHashCacheKey = (payload) => xxh3Hash(Buffer.from(JSON.stringify(payload)));
103
- const getCachedJson = (cacheKey) => {
104
- const filePath = join(getCacheDirectory(), `${cacheKey}.json`);
105
- if (!isAccessibleSync(filePath)) {
106
- return void 0;
107
- }
108
- try {
109
- const entry = readJsonSync(filePath);
110
- if (Date.now() - entry.createdAt > entry.ttlMs) {
111
- rmSync(filePath, { force: true });
112
- return void 0;
113
- }
114
- return entry.result;
115
- } catch {
116
- rmSync(filePath, { force: true });
117
- return void 0;
118
- }
119
- };
120
- const setCachedJson = (cacheKey, result, ttlMs) => {
121
- ensureCacheDirectory();
122
- const cacheDirectory = getCacheDirectory();
123
- const entry = {
124
- createdAt: Date.now(),
125
- result,
126
- ttlMs
127
- };
128
- writeFileSync(join(cacheDirectory, `${cacheKey}.json`), JSON.stringify(entry, void 0, 2), "utf8");
129
- };
130
- const clearCache = () => {
131
- const cacheDirectory = getCacheDirectory();
132
- if (!isAccessibleSync(cacheDirectory)) {
133
- return 0;
134
- }
135
- const files = readdirSync(cacheDirectory).filter((f) => f.endsWith(".json"));
136
- for (const file of files) {
137
- rmSync(join(cacheDirectory, file), { force: true });
138
- }
139
- return files.length;
140
- };
141
-
142
- export { getCachedAnalysis as a, buildCacheKey as b, clearCache as c, getTtlForAnalysisType as d, getCachedJson as e, setCachedJson as f, getCacheStats as g, buildHashCacheKey as h, setCachedAnalysis as s };