uneven-ai 1.1.2 → 1.1.4
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +23 -1
- package/dist/application/development/fix/suggest.d.ts.map +1 -1
- package/dist/application/development/fix/suggest.js +65 -3
- package/dist/application/orchestration/engine/ask.d.ts +2 -1
- package/dist/application/orchestration/engine/ask.d.ts.map +1 -1
- package/dist/application/orchestration/engine/ask.js +38 -3
- package/dist/application/orchestration/engine/context.d.ts.map +1 -1
- package/dist/application/orchestration/engine/context.js +16 -4
- package/dist/application/orchestration/engine/error-handler.d.ts +4 -0
- package/dist/application/orchestration/engine/error-handler.d.ts.map +1 -1
- package/dist/application/orchestration/engine/error-handler.js +47 -0
- package/dist/application/orchestration/engine/watcher.d.ts.map +1 -1
- package/dist/application/orchestration/engine/watcher.js +15 -6
- package/dist/cli/commands/init/command.d.ts.map +1 -1
- package/dist/cli/commands/init/command.js +17 -7
- package/dist/cli/theme.d.ts.map +1 -1
- package/dist/infrastructure/utils/error-parser/types.d.ts +1 -1
- package/dist/infrastructure/utils/error-parser/types.d.ts.map +1 -1
- package/package.json +10 -10
- package/prebuilds/darwin-arm64/uneven_core.node +0 -0
- package/prebuilds/linux-arm64/uneven_core.node +0 -0
- package/prebuilds/linux-x64/uneven_core.node +0 -0
- package/prebuilds/win32-x64/uneven_core.node +0 -0
package/CHANGELOG.md
CHANGED
|
@@ -5,7 +5,29 @@ All notable changes to Uneven AI will be documented in this file.
|
|
|
5
5
|
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),
|
|
6
6
|
and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
|
|
7
7
|
|
|
8
|
-
## [1.1.
|
|
8
|
+
## [1.1.4] - 2026-04-24
|
|
9
|
+
|
|
10
|
+
### Changed
|
|
11
|
+
- **Major Dependency Upgrade**: Migrated to **TypeScript 6.0.3** and updated all core npm dependencies (`ts-jest`, `ora`, `mongodb`, `mysql2`, etc.).
|
|
12
|
+
- **Rust Core Update**: Upgraded Rust dependencies including `tokio`, `usearch`, and `candle` for better performance and security.
|
|
13
|
+
- **Improved Init Logic**: The `init` command now performs a clean-up of old state/config before starting, ensuring a fresh installation.
|
|
14
|
+
- **Resilient Path Resolution**: Enhanced the agentic search engine to resolve files even when provided with incomplete paths.
|
|
15
|
+
- **Omni-Support Sync**: Synchronized 60+ file extensions across both TypeScript and Rust layers for consistent project indexing.
|
|
16
|
+
|
|
17
|
+
## [1.1.3] - 2026-04-24
|
|
18
|
+
|
|
19
|
+
### Added
|
|
20
|
+
|
|
21
|
+
- **Proactive AutoFix Mode**: The engine now performs "Silent Audits" on file save. It proactively scans for logic bugs, security vulnerabilities, and performance issues even if no terminal error is detected.
|
|
22
|
+
- **Omni-Support: Universal Language Expansion**: Massive update to the knowledge engine, now supporting over 60+ file extensions across all major ecosystems (Web, Mobile, Systems, DevOps, Data Science) synchronized between TS and Rust core.
|
|
23
|
+
- **Agentic Autonomy**: Maria can now perform deep-scan audits directly via chat/ask command, injecting real-time findings into the conversation context.
|
|
24
|
+
- **Intelligent Debouncing**: Refined the fix engine to handle concurrent terminal errors and proactive scans without conflicts.
|
|
25
|
+
- **Dependency Injection**: Refactored orchestration engine for better testability and ESM compatibility.
|
|
26
|
+
|
|
27
|
+
## [1.1.2] - 2026-04-24 [DEPRECATED]
|
|
28
|
+
|
|
29
|
+
> [!CAUTION]
|
|
30
|
+
> **This version is deprecated.** Users are strongly encouraged to upgrade to **v1.1.3** to benefit from the new Proactive Analysis engine and universal language support.
|
|
9
31
|
|
|
10
32
|
### Fixed
|
|
11
33
|
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"suggest.d.ts","sourceRoot":"","sources":["../../../../src/application/development/fix/suggest.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"suggest.d.ts","sourceRoot":"","sources":["../../../../src/application/development/fix/suggest.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,qDAAqD,CAAA;AAItF,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,EAAE,MAAM,cAAc,CAAA;AAKzD,wBAAsB,YAAY,CAAC,GAAG,EAAE,MAAM,EAAE,KAAK,EAAE,WAAW,GAAG,OAAO,CAAC,aAAa,GAAG,IAAI,CAAC,CA2CjG"}
|
|
@@ -1,3 +1,5 @@
|
|
|
1
|
+
import * as fs from 'fs/promises';
|
|
2
|
+
import * as path from 'path';
|
|
1
3
|
import { readCodeBlockFromFile } from '../../../infrastructure/utils/error-parser/index.js';
|
|
2
4
|
import { llmInfer, isNativeAvailable } from '../../../infrastructure/adapters/bridge.js';
|
|
3
5
|
import { extractField } from './helpers.js';
|
|
@@ -29,18 +31,78 @@ export async function doSuggestFix(ctx, error) {
|
|
|
29
31
|
}
|
|
30
32
|
}
|
|
31
33
|
let suggestion = null;
|
|
32
|
-
|
|
34
|
+
const errorType = error.type;
|
|
35
|
+
if (errorType === 'compiler')
|
|
33
36
|
suggestion = suggestCompilerFix(error);
|
|
34
|
-
else if (
|
|
37
|
+
else if (errorType === 'runtime')
|
|
35
38
|
suggestion = suggestRuntimeFix(error);
|
|
36
|
-
else if (
|
|
39
|
+
else if (errorType === 'linter')
|
|
37
40
|
suggestion = suggestLinterFix(error);
|
|
41
|
+
else if (errorType === 'proactive-scan') {
|
|
42
|
+
suggestion = await suggestProactiveScan(ctx, error);
|
|
43
|
+
}
|
|
38
44
|
if (suggestion) {
|
|
39
45
|
suggestion.afterCode = ctx.safetyGuard.sanitizeResponse(suggestion.afterCode);
|
|
40
46
|
suggestion.explanation = ctx.safetyGuard.sanitizeResponse(suggestion.explanation);
|
|
41
47
|
}
|
|
42
48
|
return suggestion;
|
|
43
49
|
}
|
|
50
|
+
/**
|
|
51
|
+
* Special handling for proactive code analysis on file save.
|
|
52
|
+
* It asks the LLM to find bugs, logic errors, or style violations.
|
|
53
|
+
*/
|
|
54
|
+
async function suggestProactiveScan(ctx, error) {
|
|
55
|
+
if (!error.file)
|
|
56
|
+
return null;
|
|
57
|
+
// Read the file to analyze its content
|
|
58
|
+
const content = await fs.readFile(error.file, 'utf-8').catch(() => '');
|
|
59
|
+
if (!content.trim())
|
|
60
|
+
return null;
|
|
61
|
+
const prompt = `You are a Senior Software Engineer and Security Auditor.
|
|
62
|
+
Analyze the following code for:
|
|
63
|
+
1. Logical bugs or edge cases not handled.
|
|
64
|
+
2. Performance bottlenecks or memory leaks.
|
|
65
|
+
3. Security vulnerabilities (SQLi, XSS, etc.).
|
|
66
|
+
4. Style or consistency issues with modern best practices.
|
|
67
|
+
|
|
68
|
+
### CODE TO ANALYZE (${path.basename(error.file)}):
|
|
69
|
+
\`\`\`
|
|
70
|
+
${content.slice(0, 4000)}
|
|
71
|
+
\`\`\`
|
|
72
|
+
|
|
73
|
+
### INSTRUCTIONS:
|
|
74
|
+
- If you find NO issues, respond exactly with: NO_ISSUES_FOUND.
|
|
75
|
+
- If you find a potential issue, respond in this exact format (no extra text):
|
|
76
|
+
EXPLANATION: <one sentence describing the issue found>
|
|
77
|
+
FIX: <specific change required>
|
|
78
|
+
AFTER_CODE: <the corrected version of the affected code block>
|
|
79
|
+
CONFIDENCE: <number between 0.0 and 1.0>`;
|
|
80
|
+
try {
|
|
81
|
+
const response = await llmInfer(prompt, 512);
|
|
82
|
+
const text = response.content.trim();
|
|
83
|
+
if (text.includes('NO_ISSUES_FOUND')) {
|
|
84
|
+
return null;
|
|
85
|
+
}
|
|
86
|
+
const explanation = extractField(text, 'EXPLANATION') ?? '';
|
|
87
|
+
const suggestedFix = extractField(text, 'FIX') ?? '';
|
|
88
|
+
const afterCode = extractField(text, 'AFTER_CODE') ?? '';
|
|
89
|
+
const confidence = parseFloat(extractField(text, 'CONFIDENCE') ?? '0.0');
|
|
90
|
+
if (!explanation || !suggestedFix)
|
|
91
|
+
return null;
|
|
92
|
+
return {
|
|
93
|
+
error,
|
|
94
|
+
explanation,
|
|
95
|
+
suggestedFix,
|
|
96
|
+
beforeCode: '', // Not used for proactive scan
|
|
97
|
+
afterCode,
|
|
98
|
+
confidence: isNaN(confidence) ? 0.7 : confidence,
|
|
99
|
+
};
|
|
100
|
+
}
|
|
101
|
+
catch (err) {
|
|
102
|
+
ctx.logger.debug(`Proactive: LLM analysis failed: ${err}`);
|
|
103
|
+
return null;
|
|
104
|
+
}
|
|
105
|
+
}
|
|
44
106
|
async function suggestRAFFix(ctx, error, context) {
|
|
45
107
|
const score = context.avgScore;
|
|
46
108
|
const confidence = score >= 0.85 ? 0.92 : score >= 0.70 ? 0.78 : 0.65;
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import { FixEngine } from '../../development/fix/index.js';
|
|
1
2
|
import type { EngineCtx } from './context.js';
|
|
2
3
|
/**
|
|
3
4
|
* doAsk — Knowledge Map Strategy
|
|
@@ -9,5 +10,5 @@ import type { EngineCtx } from './context.js';
|
|
|
9
10
|
export declare function doAsk(ctx: EngineCtx, question: string, onToken?: (token: string) => void, history?: Array<{
|
|
10
11
|
role: 'user' | 'assistant';
|
|
11
12
|
content: string;
|
|
12
|
-
}
|
|
13
|
+
}>, fixEngineOverride?: FixEngine): Promise<string>;
|
|
13
14
|
//# sourceMappingURL=ask.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"ask.d.ts","sourceRoot":"","sources":["../../../../src/application/orchestration/engine/ask.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"ask.d.ts","sourceRoot":"","sources":["../../../../src/application/orchestration/engine/ask.ts"],"names":[],"mappings":"AAaA,OAAO,EAAE,SAAS,EAAE,MAAM,gCAAgC,CAAA;AAE1D,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,cAAc,CAAA;AAE7C;;;;;;GAMG;AACH,wBAAsB,KAAK,CACzB,GAAG,EAAE,SAAS,EACd,QAAQ,EAAE,MAAM,EAChB,OAAO,CAAC,EAAE,CAAC,KAAK,EAAE,MAAM,KAAK,IAAI,EACjC,OAAO,GAAE,KAAK,CAAC;IAAE,IAAI,EAAE,MAAM,GAAG,WAAW,CAAC;IAAC,OAAO,EAAE,MAAM,CAAA;CAAE,CAAM,EACpE,iBAAiB,CAAC,EAAE,SAAS,GAC5B,OAAO,CAAC,MAAM,CAAC,CA2IjB"}
|
|
@@ -1,8 +1,11 @@
|
|
|
1
1
|
import * as fs from 'fs/promises';
|
|
2
|
+
import * as fsSync from 'fs';
|
|
2
3
|
import * as path from 'path';
|
|
3
4
|
import { isNativeAvailable, llmEmbed, llmInfer, llmInferStream, retrievalSearch, } from '../../../infrastructure/adapters/bridge.js';
|
|
4
5
|
import { ExternalProviders } from '../../../infrastructure/adapters/providers/index.js';
|
|
5
6
|
import { resetUnloadTimer } from './lifecycle.js';
|
|
7
|
+
import { FixEngine } from '../../development/fix/index.js';
|
|
8
|
+
import { KnowledgeRetriever } from '../knowledge-retriever.js';
|
|
6
9
|
/**
|
|
7
10
|
* doAsk — Knowledge Map Strategy
|
|
8
11
|
*
|
|
@@ -10,7 +13,7 @@ import { resetUnloadTimer } from './lifecycle.js';
|
|
|
10
13
|
* 2. Phase 1: Ask LLM which paths are relevant.
|
|
11
14
|
* 3. Phase 2: Read relevant files and generate final answer.
|
|
12
15
|
*/
|
|
13
|
-
export async function doAsk(ctx, question, onToken, history = []) {
|
|
16
|
+
export async function doAsk(ctx, question, onToken, history = [], fixEngineOverride) {
|
|
14
17
|
if (!ctx.initialized)
|
|
15
18
|
throw new Error('Uneven not initialized');
|
|
16
19
|
try {
|
|
@@ -26,15 +29,47 @@ export async function doAsk(ctx, question, onToken, history = []) {
|
|
|
26
29
|
ctx.logger.debug(`Relevant paths detected: ${relevantPaths.join(', ') || 'none'}`);
|
|
27
30
|
// 3. Phase 2: Context Assembly (Read files)
|
|
28
31
|
let context = '## RELEVANT CONTEXT (KNOWLEDGE MAP)\n\n';
|
|
32
|
+
const isAuditRequest = /audit|scan|scanear|analis|bug|error|erro|corrig|fix/i.test(question);
|
|
29
33
|
if (relevantPaths.length > 0) {
|
|
34
|
+
const retriever = new KnowledgeRetriever(ctx.logger);
|
|
35
|
+
const fixEngine = fixEngineOverride ?? new FixEngine(ctx.logger, ctx.projectRoot, retriever);
|
|
30
36
|
for (const relPath of relevantPaths) {
|
|
31
37
|
try {
|
|
32
|
-
|
|
38
|
+
let absPath = path.resolve(ctx.projectRoot, relPath);
|
|
39
|
+
// Fallback: If LLM returned only filename, try to find it in the files map
|
|
40
|
+
if (!fsSync.existsSync(absPath)) {
|
|
41
|
+
const fullMap = filesMap.split('\n');
|
|
42
|
+
const found = fullMap.find(p => p.endsWith(relPath) || p.endsWith('/' + relPath));
|
|
43
|
+
if (found) {
|
|
44
|
+
absPath = path.resolve(ctx.projectRoot, found);
|
|
45
|
+
}
|
|
46
|
+
}
|
|
33
47
|
const content = await fs.readFile(absPath, 'utf8');
|
|
34
48
|
context += `**File: ${relPath}**\n\`\`\`\n${content}\n\`\`\`\n\n`;
|
|
49
|
+
// Agentic Autonomy: If it's an audit request, run a proactive scan too
|
|
50
|
+
if (isAuditRequest) {
|
|
51
|
+
const virtualError = {
|
|
52
|
+
type: 'proactive-scan',
|
|
53
|
+
severity: 'info',
|
|
54
|
+
code: 'SCAN',
|
|
55
|
+
message: 'Agentic audit request.',
|
|
56
|
+
file: absPath,
|
|
57
|
+
line: 0,
|
|
58
|
+
column: 0,
|
|
59
|
+
context: [],
|
|
60
|
+
fullOutput: 'AGENTIC_AUDIT_TRIGGERED'
|
|
61
|
+
};
|
|
62
|
+
const suggestion = await fixEngine.suggestFix(virtualError);
|
|
63
|
+
if (suggestion && suggestion.confidence > 0.6) {
|
|
64
|
+
context += `**[MARIA AUDIT FINDING for ${relPath}]**\n`;
|
|
65
|
+
context += `ISSUE: ${suggestion.explanation}\n`;
|
|
66
|
+
context += `PROPOSED_FIX: ${suggestion.suggestedFix}\n`;
|
|
67
|
+
context += `CODE_CHANGE:\n${suggestion.afterCode}\n\n`;
|
|
68
|
+
}
|
|
69
|
+
}
|
|
35
70
|
}
|
|
36
71
|
catch (e) {
|
|
37
|
-
ctx.logger.warning(`Failed to read relevant file ${relPath}: ${e}`);
|
|
72
|
+
ctx.logger.warning(`Failed to read or audit relevant file ${relPath}: ${e}`);
|
|
38
73
|
}
|
|
39
74
|
}
|
|
40
75
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"context.d.ts","sourceRoot":"","sources":["../../../../src/application/orchestration/engine/context.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,YAAY,EAAE,SAAS,EAAE,MAAM,4BAA4B,CAAA;AACzE,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,4CAA4C,CAAA;AACxE,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,2CAA2C,CAAA;AAC/E,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,yBAAyB,CAAA;AAC/D,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,0CAA0C,CAAA;AAC3E,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,+CAA+C,CAAA;AACrF,OAAO,KAAK,EAAE,mBAAmB,EAAE,MAAM,yCAAyC,CAAA;AAElF,eAAO,MAAM,YAAY,aAIvB,CAAA;AAEF,eAAO,MAAM,oBAAoB,
|
|
1
|
+
{"version":3,"file":"context.d.ts","sourceRoot":"","sources":["../../../../src/application/orchestration/engine/context.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,YAAY,EAAE,SAAS,EAAE,MAAM,4BAA4B,CAAA;AACzE,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,4CAA4C,CAAA;AACxE,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,2CAA2C,CAAA;AAC/E,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,yBAAyB,CAAA;AAC/D,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,0CAA0C,CAAA;AAC3E,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,+CAA+C,CAAA;AACrF,OAAO,KAAK,EAAE,mBAAmB,EAAE,MAAM,yCAAyC,CAAA;AAElF,eAAO,MAAM,YAAY,aAIvB,CAAA;AAEF,eAAO,MAAM,oBAAoB,aAkB/B,CAAA;AAEF,eAAO,MAAM,kBAAkB,aAA0E,CAAA;AAEzG,MAAM,WAAW,SAAS;IACxB,MAAM,EAAE,YAAY,CAAA;IACpB,MAAM,EAAE,MAAM,CAAA;IACd,OAAO,EAAE,cAAc,CAAA;IACvB,gBAAgB,EAAE,gBAAgB,CAAA;IAClC,WAAW,EAAE,OAAO,CAAA;IACpB,OAAO,EAAE,OAAO,CAAA;IAChB,WAAW,EAAE,GAAG,CAAC,MAAM,CAAC,CAAA;IACxB,WAAW,EAAE,MAAM,CAAC,OAAO,GAAG,IAAI,CAAA;IAClC,kBAAkB,EAAE,GAAG,CAAC,MAAM,EAAE,MAAM,CAAC,CAAA;IACvC,YAAY,EAAE,GAAG,CAAC,MAAM,EAAE,OAAO,CAAC,IAAI,CAAC,CAAC,CAAA;IACxC,cAAc,EAAE,GAAG,CAAC,MAAM,EAAE,MAAM,CAAC,OAAO,CAAC,CAAA;IAC3C,WAAW,EAAE,WAAW,CAAA;IACxB,YAAY,EAAE,mBAAmB,CAAA;IACjC,gBAAgB,EAAE,gBAAgB,CAAA;IAClC,UAAU,EAAE,CAAC,MAAM,IAAI,CAAC,GAAG,IAAI,CAAA;IAC/B,WAAW,EAAE,MAAM,CAAA;IACnB,SAAS,CAAC,IAAI,EAAE,SAAS,EAAE,IAAI,EAAE,OAAO,GAAG,IAAI,CAAA;CAChD"}
|
|
@@ -4,10 +4,22 @@ export const IGNORED_DIRS = new Set([
|
|
|
4
4
|
'tests', 'test', 'spec', 'mocks', '__tests__',
|
|
5
5
|
]);
|
|
6
6
|
export const SUPPORTED_EXTENSIONS = new Set([
|
|
7
|
-
|
|
8
|
-
'.
|
|
9
|
-
'.
|
|
7
|
+
// Web & Frontend (Frameworks: React, Vue, Svelte, Astro, etc.)
|
|
8
|
+
'.ts', '.tsx', '.js', '.jsx', '.vue', '.svelte', '.astro', '.html', '.css', '.scss', '.sass', '.less', '.pcss', '.styl',
|
|
9
|
+
'.json', '.md', '.txt', '.yaml', '.yml', '.sql', '.xml', '.svg', '.graphql', '.gql',
|
|
10
|
+
// Templating
|
|
11
|
+
'.pug', '.jade', '.twig', '.hbs', '.ejs', '.liquid',
|
|
12
|
+
// Backend & Systems (Rust, Go, C++, Java, C#, PHP, Ruby, etc.)
|
|
13
|
+
'.rs', '.py', '.pyi', '.go', '.java', '.kt', '.kts', '.swift', '.m', '.h', '.cpp', '.c', '.cc', '.hh', '.hpp',
|
|
14
|
+
'.cs', '.lua', '.php', '.rb', '.ex', '.exs', '.erl', '.hrl', '.fs', '.nim', '.zig', '.sol',
|
|
15
|
+
// Functional Programming
|
|
16
|
+
'.scala', '.sc', '.groovy', '.clj', '.cljs', '.cljc', '.edn', '.hs', '.lhs', '.ml', '.mli', '.pl', '.pro', '.lisp', '.scm', '.cl', '.el',
|
|
17
|
+
// Data Science, AI & Analysis
|
|
18
|
+
'.r', '.jl', '.ipynb', '.f', '.f90', '.f95',
|
|
19
|
+
// Infrastructure, DevOps & Config
|
|
20
|
+
'.toml', '.prisma', '.proto', '.dockerfile', '.dockerignore', '.tf', '.tfvars', '.hcl', '.ini', '.conf', '.editorconfig', '.env.example',
|
|
21
|
+
'.sh', '.bash', '.zsh', '.cbl', '.cob', '.asm', '.s', '.v', '.vhdl',
|
|
22
|
+
// Documents & Data
|
|
10
23
|
'.xls', '.xlsx', '.csv', '.docx', '.pdf',
|
|
11
|
-
'.cbl', '.cob', '.asm', '.s',
|
|
12
24
|
]);
|
|
13
25
|
export const IGNORED_EXTENSIONS = new Set(['.env', '.pem', '.key', '.crt', '.pfx', '.db-shm', '.db-wal']);
|
|
@@ -2,6 +2,10 @@ import type { FixEngine } from '../../development/fix/index.js';
|
|
|
2
2
|
import type { PendingDiff } from '../../../domain/entities/session/index.js';
|
|
3
3
|
import type { EngineCtx } from './context.js';
|
|
4
4
|
export declare function handleErrorFix(ctx: EngineCtx, error: any, fixEngine: FixEngine, confirmBeforeFix: boolean): void;
|
|
5
|
+
/**
|
|
6
|
+
* Handle proactive fixes triggered by file changes (without explicit terminal errors).
|
|
7
|
+
*/
|
|
8
|
+
export declare function handleProactiveFix(ctx: EngineCtx, filePath: string, fixEngine: FixEngine, confirmBeforeFix: boolean): void;
|
|
5
9
|
export declare function runFixForError(ctx: EngineCtx, error: any, fixKey: string, fixEngine: FixEngine, confirmBeforeFix: boolean): Promise<void>;
|
|
6
10
|
export declare function applyPendingDiff(ctx: EngineCtx, diff: PendingDiff, fixEngine: FixEngine): Promise<void>;
|
|
7
11
|
//# sourceMappingURL=error-handler.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"error-handler.d.ts","sourceRoot":"","sources":["../../../../src/application/orchestration/engine/error-handler.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,SAAS,EAAiB,MAAM,gCAAgC,CAAA;AAC9E,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,2CAA2C,CAAA;
|
|
1
|
+
{"version":3,"file":"error-handler.d.ts","sourceRoot":"","sources":["../../../../src/application/orchestration/engine/error-handler.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,SAAS,EAAiB,MAAM,gCAAgC,CAAA;AAC9E,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,2CAA2C,CAAA;AAE5E,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,cAAc,CAAA;AAE7C,wBAAgB,cAAc,CAC5B,GAAG,EAAE,SAAS,EACd,KAAK,EAAE,GAAG,EACV,SAAS,EAAE,SAAS,EACpB,gBAAgB,EAAE,OAAO,GACxB,IAAI,CAoCN;AAED;;GAEG;AACH,wBAAgB,kBAAkB,CAChC,GAAG,EAAE,SAAS,EACd,QAAQ,EAAE,MAAM,EAChB,SAAS,EAAE,SAAS,EACpB,gBAAgB,EAAE,OAAO,GACxB,IAAI,CA8CN;AAED,wBAAsB,cAAc,CAClC,GAAG,EAAE,SAAS,EACd,KAAK,EAAE,GAAG,EACV,MAAM,EAAE,MAAM,EACd,SAAS,EAAE,SAAS,EACpB,gBAAgB,EAAE,OAAO,GACxB,OAAO,CAAC,IAAI,CAAC,CAsGf;AAED,wBAAsB,gBAAgB,CAAC,GAAG,EAAE,SAAS,EAAE,IAAI,EAAE,WAAW,EAAE,SAAS,EAAE,SAAS,GAAG,OAAO,CAAC,IAAI,CAAC,CAwC7G"}
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import * as path from 'path';
|
|
1
2
|
export function handleErrorFix(ctx, error, fixEngine, confirmBeforeFix) {
|
|
2
3
|
const fixKey = `${error.file ?? 'unknown'}:${error.line ?? 0}`;
|
|
3
4
|
const fileKey = error.file ?? 'unknown';
|
|
@@ -30,6 +31,52 @@ export function handleErrorFix(ctx, error, fixEngine, confirmBeforeFix) {
|
|
|
30
31
|
ctx.fileFixQueue.delete(fileKey);
|
|
31
32
|
});
|
|
32
33
|
}
|
|
34
|
+
/**
|
|
35
|
+
* Handle proactive fixes triggered by file changes (without explicit terminal errors).
|
|
36
|
+
*/
|
|
37
|
+
export function handleProactiveFix(ctx, filePath, fixEngine, confirmBeforeFix) {
|
|
38
|
+
const fixKey = `proactive:${filePath}`;
|
|
39
|
+
const fileKey = filePath;
|
|
40
|
+
// Prevent spamming analysis for the same file if already active
|
|
41
|
+
if (ctx.activeFixes.has(fixKey))
|
|
42
|
+
return;
|
|
43
|
+
// Debounce: wait 1.5s after the last save to avoid scanning while typing/saving fast
|
|
44
|
+
const existingTimer = ctx.debounceTimers.get(fixKey);
|
|
45
|
+
if (existingTimer)
|
|
46
|
+
clearTimeout(existingTimer);
|
|
47
|
+
const timer = setTimeout(async () => {
|
|
48
|
+
ctx.debounceTimers.delete(fixKey);
|
|
49
|
+
// If there's an active terminal error fix for this file, skip proactive scan
|
|
50
|
+
if (ctx.activeFixes.has(fileKey)) {
|
|
51
|
+
ctx.logger.debug(`Proactive: skipping scan for ${filePath} because a terminal fix is active.`);
|
|
52
|
+
return;
|
|
53
|
+
}
|
|
54
|
+
ctx.activeFixes.add(fixKey);
|
|
55
|
+
try {
|
|
56
|
+
const virtualError = {
|
|
57
|
+
type: 'proactive-scan',
|
|
58
|
+
severity: 'info',
|
|
59
|
+
code: 'SCAN',
|
|
60
|
+
message: 'Proactive quality and bug scan requested on file save.',
|
|
61
|
+
file: filePath,
|
|
62
|
+
line: 0,
|
|
63
|
+
column: 0,
|
|
64
|
+
context: [],
|
|
65
|
+
fullOutput: 'PROACTIVE_SCAN_TRIGGERED'
|
|
66
|
+
};
|
|
67
|
+
ctx.logger.debug(`Proactive: analyzing ${path.basename(filePath)} for bugs/improvements...`);
|
|
68
|
+
// We ALWAYS force confirmation for proactive fixes to avoid unwanted changes
|
|
69
|
+
await runFixForError(ctx, virtualError, fixKey, fixEngine, true);
|
|
70
|
+
}
|
|
71
|
+
catch (err) {
|
|
72
|
+
ctx.logger.debug(`Proactive: scan failed for ${filePath}: ${err}`);
|
|
73
|
+
}
|
|
74
|
+
finally {
|
|
75
|
+
ctx.activeFixes.delete(fixKey);
|
|
76
|
+
}
|
|
77
|
+
}, 1500); // 1.5s debounce for proactive scans
|
|
78
|
+
ctx.debounceTimers.set(fixKey, timer);
|
|
79
|
+
}
|
|
33
80
|
export async function runFixForError(ctx, error, fixKey, fixEngine, confirmBeforeFix) {
|
|
34
81
|
const isActive = ctx.running || ctx.initialized;
|
|
35
82
|
if (!isActive) {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"watcher.d.ts","sourceRoot":"","sources":["../../../../src/application/orchestration/engine/watcher.ts"],"names":[],"mappings":"AAMA,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,cAAc,CAAA;AAE7C,wBAAsB,OAAO,CAAC,GAAG,EAAE,SAAS,GAAG,OAAO,CAAC,IAAI,CAAC,
|
|
1
|
+
{"version":3,"file":"watcher.d.ts","sourceRoot":"","sources":["../../../../src/application/orchestration/engine/watcher.ts"],"names":[],"mappings":"AAMA,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,cAAc,CAAA;AAE7C,wBAAsB,OAAO,CAAC,GAAG,EAAE,SAAS,GAAG,OAAO,CAAC,IAAI,CAAC,CAsJ3D"}
|
|
@@ -48,10 +48,24 @@ export async function doWatch(ctx) {
|
|
|
48
48
|
watcher: new ProcessWatcher({ command: cmd, autoRestart: true, maxRestarts: 3 }, ctx.logger),
|
|
49
49
|
}));
|
|
50
50
|
const watchDirs = ctx.config.knowledge?.dirs?.length ? ctx.config.knowledge.dirs : [process.cwd()];
|
|
51
|
-
const
|
|
51
|
+
const { SUPPORTED_EXTENSIONS } = await import('./context.js');
|
|
52
|
+
const fileWatcher = new FileWatcher({
|
|
53
|
+
paths: watchDirs,
|
|
54
|
+
extensions: Array.from(SUPPORTED_EXTENSIONS)
|
|
55
|
+
}, ctx.logger);
|
|
56
|
+
const retriever = new KnowledgeRetriever(ctx.logger);
|
|
57
|
+
const fixEngine = new FixEngine(ctx.logger, ctx.projectRoot, retriever, {
|
|
58
|
+
acquire: (name) => ctx.session.acquireLock(name),
|
|
59
|
+
release: (lockId) => ctx.session.releaseLock(lockId),
|
|
60
|
+
});
|
|
61
|
+
const { handleProactiveFix } = await import('./error-handler.js');
|
|
52
62
|
fileWatcher.on('change', (filePath) => {
|
|
53
63
|
ctx.logger.info(`FileWatcher: change detected — ${filePath}`);
|
|
54
64
|
ctx.emitEvent('file-changed', { path: filePath });
|
|
65
|
+
if (autoFix) {
|
|
66
|
+
// Trigger proactive analysis on save
|
|
67
|
+
handleProactiveFix(ctx, filePath, fixEngine, confirmBeforeFix);
|
|
68
|
+
}
|
|
55
69
|
});
|
|
56
70
|
fileWatcher.on('add', (filePath) => {
|
|
57
71
|
ctx.logger.debug(`FileWatcher: new file — ${filePath}`);
|
|
@@ -62,11 +76,6 @@ export async function doWatch(ctx) {
|
|
|
62
76
|
ctx.emitEvent('file-removed', { path: filePath });
|
|
63
77
|
});
|
|
64
78
|
await fileWatcher.start();
|
|
65
|
-
const retriever = new KnowledgeRetriever(ctx.logger);
|
|
66
|
-
const fixEngine = new FixEngine(ctx.logger, ctx.projectRoot, retriever, {
|
|
67
|
-
acquire: (name) => ctx.session.acquireLock(name),
|
|
68
|
-
release: (lockId) => ctx.session.releaseLock(lockId),
|
|
69
|
-
});
|
|
70
79
|
let errorCount = 0;
|
|
71
80
|
let stoppedCount = 0;
|
|
72
81
|
for (const { label, watcher } of watchers) {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"command.d.ts","sourceRoot":"","sources":["../../../../src/cli/commands/init/command.ts"],"names":[],"mappings":"AAeA,wBAAsB,WAAW,IAAI,OAAO,CAAC,IAAI,CAAC,
|
|
1
|
+
{"version":3,"file":"command.d.ts","sourceRoot":"","sources":["../../../../src/cli/commands/init/command.ts"],"names":[],"mappings":"AAeA,wBAAsB,WAAW,IAAI,OAAO,CAAC,IAAI,CAAC,CAuKjD"}
|
|
@@ -41,11 +41,22 @@ export async function initCommand() {
|
|
|
41
41
|
console.log(t.dim(' This will only take a moment.'));
|
|
42
42
|
console.log();
|
|
43
43
|
const spinner = ora({ text: t.dim('Preparing workspace...'), color: 'blue' }).start();
|
|
44
|
+
// 1. Pre-init Cleanup (as requested by user)
|
|
45
|
+
// We remove existing state/logs but keep models to avoid 1.4GB redownload
|
|
46
|
+
try {
|
|
47
|
+
await fs.rm('.uneven/cache', { recursive: true, force: true });
|
|
48
|
+
await fs.rm('.uneven/logs', { recursive: true, force: true });
|
|
49
|
+
await fs.rm('.uneven/index-state.json', { force: true });
|
|
50
|
+
await fs.rm('.uneven/config.json', { force: true });
|
|
51
|
+
await fs.rm('.uneven/vectors.json', { force: true });
|
|
52
|
+
await fs.rm('uneven-reports', { recursive: true, force: true });
|
|
53
|
+
}
|
|
54
|
+
catch { /* ignore */ }
|
|
44
55
|
await fs.mkdir('.uneven/cache', { recursive: true });
|
|
45
56
|
await fs.mkdir('.uneven/models', { recursive: true });
|
|
46
57
|
await fs.mkdir('.uneven/logs', { recursive: true });
|
|
47
58
|
await fs.mkdir('uneven-reports', { recursive: true });
|
|
48
|
-
spinner.succeed(t.crystal('Workspace
|
|
59
|
+
spinner.succeed(t.crystal('Workspace prepared') + t.dim(' (Cleaned and ready)'));
|
|
49
60
|
section('Which brain should power Uneven?');
|
|
50
61
|
const providers = [
|
|
51
62
|
{ key: '1', id: 'local', label: 'Maria', note: `${chalk.green('Recommended:')} 100% Private and Sovereign` },
|
|
@@ -71,13 +82,12 @@ export async function initCommand() {
|
|
|
71
82
|
blank();
|
|
72
83
|
ok(`Brain set to ${t.bright(PROVIDER_LABELS[provider] ?? provider)}`);
|
|
73
84
|
const newConfigPath = path.join(process.cwd(), 'uneven.config.ts');
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
}
|
|
77
|
-
else {
|
|
78
|
-
await fs.writeFile(newConfigPath, makeConfig(provider, recommendedThreads, recommendedGpuLayers));
|
|
79
|
-
ok('uneven.config.ts created');
|
|
85
|
+
try {
|
|
86
|
+
await fs.rm(newConfigPath, { force: true });
|
|
80
87
|
}
|
|
88
|
+
catch { /* ignore */ }
|
|
89
|
+
await fs.writeFile(newConfigPath, makeConfig(provider, recommendedThreads, recommendedGpuLayers));
|
|
90
|
+
ok('uneven.config.ts created');
|
|
81
91
|
await saveConfig({
|
|
82
92
|
brain: {
|
|
83
93
|
provider: provider,
|
package/dist/cli/theme.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"theme.d.ts","sourceRoot":"","sources":["../../src/cli/theme.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;GAUG;AAMH,eAAO,MAAM,CAAC;gBACE,MAAM;gBACN,MAAM;iBACN,MAAM;aACN,MAAM;eACN,MAAM;cACN,MAAM;cACN,MAAM;oBACJ,MAAM;CACvB,CAAA;AAUD,eAAO,MAAM,GAAG;IACd,oCAAoC;oBACpB,MAAM,GAAG,IAAI;IAa7B,sBAAsB;eACX,IAAI;IAIf,qCAAqC;kBACvB,KAAK,CAAC;QAAE,IAAI,EAAE,MAAM,CAAC;QAAC,KAAK,EAAE,MAAM,CAAC;QAAC,KAAK,CAAC,EAAE,MAAM,CAAA;KAAE,CAAC,GAAG,IAAI;CAW5E,CAAA;AAID,wBAAgB,OAAO,CAAC,KAAK,EAAE,MAAM,GAAG,IAAI,CAI3C;AAID,eAAO,MAAM,EAAE,
|
|
1
|
+
{"version":3,"file":"theme.d.ts","sourceRoot":"","sources":["../../src/cli/theme.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;GAUG;AAMH,eAAO,MAAM,CAAC;gBACE,MAAM;gBACN,MAAM;iBACN,MAAM;aACN,MAAM;eACN,MAAM;cACN,MAAM;cACN,MAAM;oBACJ,MAAM;CACvB,CAAA;AAUD,eAAO,MAAM,GAAG;IACd,oCAAoC;oBACpB,MAAM,GAAG,IAAI;IAa7B,sBAAsB;eACX,IAAI;IAIf,qCAAqC;kBACvB,KAAK,CAAC;QAAE,IAAI,EAAE,MAAM,CAAC;QAAC,KAAK,EAAE,MAAM,CAAC;QAAC,KAAK,CAAC,EAAE,MAAM,CAAA;KAAE,CAAC,GAAG,IAAI;CAW5E,CAAA;AAID,wBAAgB,OAAO,CAAC,KAAK,EAAE,MAAM,GAAG,IAAI,CAI3C;AAID,eAAO,MAAM,EAAE,GAAO,KAAK,MAAM,SAAmD,CAAA;AACpF,eAAO,MAAM,IAAI,GAAK,KAAK,MAAM,SAAmD,CAAA;AACpF,eAAO,MAAM,IAAI,GAAK,KAAK,MAAM,SAAmD,CAAA;AACpF,eAAO,MAAM,IAAI,GAAK,KAAK,MAAM,SAAgD,CAAA;AACjF,eAAO,MAAM,IAAI,GAAK,KAAK,MAAM,SAAsC,CAAA;AACvE,eAAO,MAAM,KAAK,YAAiC,CAAA;AAInD,wBAAgB,OAAO,CAAC,GAAG,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,GAAG,IAAI,CAGvD;AAID,eAAO,MAAM,eAAe,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAMlD,CAAA"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../../../src/infrastructure/utils/error-parser/types.ts"],"names":[],"mappings":"AAAA,MAAM,WAAW,WAAW;IAC1B,IAAI,EAAE,UAAU,GAAG,SAAS,GAAG,QAAQ,GAAG,MAAM,GAAG,SAAS,CAAA;
|
|
1
|
+
{"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../../../src/infrastructure/utils/error-parser/types.ts"],"names":[],"mappings":"AAAA,MAAM,WAAW,WAAW;IAC1B,IAAI,EAAE,UAAU,GAAG,SAAS,GAAG,QAAQ,GAAG,MAAM,GAAG,gBAAgB,GAAG,SAAS,CAAA;IAC/E,QAAQ,EAAE,OAAO,GAAG,SAAS,GAAG,MAAM,CAAA;IACtC,IAAI,EAAE,MAAM,CAAA;IACZ,IAAI,EAAE,MAAM,CAAA;IACZ,MAAM,EAAE,MAAM,CAAA;IACd,OAAO,EAAE,MAAM,CAAA;IACf,IAAI,EAAE,MAAM,CAAA;IACZ,OAAO,EAAE,MAAM,EAAE,CAAA;IACjB,UAAU,EAAE,MAAM,CAAA;CACnB"}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "uneven-ai",
|
|
3
|
-
"version": "1.1.
|
|
3
|
+
"version": "1.1.4",
|
|
4
4
|
"publishConfig": {
|
|
5
5
|
"access": "public",
|
|
6
6
|
"registry": "https://registry.npmjs.org/"
|
|
@@ -70,12 +70,12 @@
|
|
|
70
70
|
"exceljs": "^4.4.0",
|
|
71
71
|
"knex": "^3.2.9",
|
|
72
72
|
"mammoth": "^1.12.0",
|
|
73
|
-
"mongodb": "^7.
|
|
74
|
-
"mysql2": "^3.
|
|
75
|
-
"ora": "^9.
|
|
76
|
-
"pdfjs-dist": "^5.
|
|
73
|
+
"mongodb": "^7.2.0",
|
|
74
|
+
"mysql2": "^3.22.2",
|
|
75
|
+
"ora": "^9.4.0",
|
|
76
|
+
"pdfjs-dist": "^5.6.205",
|
|
77
77
|
"pg": "^8.20.0",
|
|
78
|
-
"undici": "^8.0
|
|
78
|
+
"undici": "^8.1.0"
|
|
79
79
|
},
|
|
80
80
|
"overrides": {
|
|
81
81
|
"chokidar": "^5.0.0"
|
|
@@ -89,9 +89,9 @@
|
|
|
89
89
|
"@typescript-eslint/utils": "^8.58.0",
|
|
90
90
|
"eslint": "^10.2.0",
|
|
91
91
|
"jest": "^29.0.0",
|
|
92
|
-
"jest-junit": "^
|
|
93
|
-
"prettier": "^3.8.
|
|
94
|
-
"ts-jest": "^29.
|
|
95
|
-
"typescript": "^
|
|
92
|
+
"jest-junit": "^17.0.0",
|
|
93
|
+
"prettier": "^3.8.3",
|
|
94
|
+
"ts-jest": "^29.4.9",
|
|
95
|
+
"typescript": "^6.0.3"
|
|
96
96
|
}
|
|
97
97
|
}
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|