@ateriss_/aiv-cli 0.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1,27 @@
1
+ import { LLMProvider, LLMMessage, LLMResponse } from './base';
2
+
3
+ export class MockProvider implements LLMProvider {
4
+ readonly name = 'mock';
5
+ readonly model = 'mock-model';
6
+
7
+ async complete(_messages: LLMMessage[], _systemPrompt?: string): Promise<LLMResponse> {
8
+ return {
9
+ content: JSON.stringify({
10
+ summary: 'Mock review: This is a test response from the mock provider.',
11
+ findings: [
12
+ {
13
+ severity: 'low',
14
+ category: 'test',
15
+ title: 'Mock Finding',
16
+ description: 'This is a placeholder finding from the mock provider.',
17
+ suggestion: 'Replace mock provider with a real one.',
18
+ },
19
+ ],
20
+ riskScore: 10,
21
+ possibleRegressions: ['Mock regression note'],
22
+ }),
23
+ inputTokens: 100,
24
+ outputTokens: 100,
25
+ };
26
+ }
27
+ }
@@ -0,0 +1,41 @@
1
+ import OpenAI from 'openai';
2
+ import { LLMProvider, LLMMessage, LLMResponse } from './base';
3
+
4
+ export class OpenAIProvider implements LLMProvider {
5
+ readonly name: string;
6
+ readonly model: string;
7
+ private readonly client: OpenAI;
8
+
9
+ constructor(apiKey: string, model: string = 'gpt-4.1', baseURL?: string, name: string = 'openai') {
10
+ this.name = name;
11
+ this.model = model;
12
+ this.client = new OpenAI({ apiKey, ...(baseURL ? { baseURL } : {}) });
13
+ }
14
+
15
+ async complete(messages: LLMMessage[], systemPrompt?: string, maxTokens: number = 4096): Promise<LLMResponse> {
16
+ const allMessages: OpenAI.Chat.ChatCompletionMessageParam[] = [];
17
+
18
+ if (systemPrompt) {
19
+ allMessages.push({ role: 'system', content: systemPrompt });
20
+ }
21
+
22
+ allMessages.push(
23
+ ...messages.map(m => ({
24
+ role: m.role as 'user' | 'assistant',
25
+ content: m.content,
26
+ }))
27
+ );
28
+
29
+ const response = await this.client.chat.completions.create({
30
+ model: this.model,
31
+ max_tokens: maxTokens,
32
+ messages: allMessages,
33
+ });
34
+
35
+ return {
36
+ content: response.choices[0]?.message?.content ?? '',
37
+ inputTokens: response.usage?.prompt_tokens,
38
+ outputTokens: response.usage?.completion_tokens,
39
+ };
40
+ }
41
+ }
package/src/types.ts ADDED
@@ -0,0 +1,175 @@
1
+ // ─── GitHub account ───────────────────────────────────────────────────────────
2
+
3
+ export interface GithubAccount {
4
+ token_env: string;
5
+ username?: string;
6
+ description?: string;
7
+ }
8
+
9
+ // ─── Global config (~/.aiv/config.yml) ───────────────────────────────────────
10
+ // Agent providers, model settings, default GH account.
11
+ // Shared across all repos on this machine.
12
+
13
+ export interface CustomProviderConfig {
14
+ base_url: string;
15
+ api_key_env: string;
16
+ model: string;
17
+ }
18
+
19
+ export interface BuiltinProviderConfig {
20
+ model: string;
21
+ api_key_env: string;
22
+ }
23
+
24
+ export interface GlobalConfig {
25
+ lang?: 'en' | 'es';
26
+ providers: {
27
+ default: string; // 'claude' | 'openai' | 'gemini' | 'mock' | custom name
28
+ fallback?: string[];
29
+ agents?: Record<string, string>; // { business: 'claude/claude-sonnet-4-6', security: 'kimi' }
30
+ };
31
+ claude?: BuiltinProviderConfig;
32
+ openai?: BuiltinProviderConfig;
33
+ gemini?: BuiltinProviderConfig;
34
+ custom_providers?: Record<string, CustomProviderConfig>;
35
+ review?: {
36
+ max_tokens: number;
37
+ max_findings: number;
38
+ };
39
+ github: {
40
+ default_account: string;
41
+ accounts: Record<string, GithubAccount>;
42
+ };
43
+ }
44
+
45
+ // ─── Repo config (.aiv/config.yml) ────────────────────────────────────────────
46
+ // Per-repository overrides: which GH account to use, owner/repo, token limits.
47
+
48
+ export interface RepoConfig {
49
+ github?: {
50
+ account?: string; // references a name in GlobalConfig.github.accounts
51
+ owner?: string;
52
+ repo?: string;
53
+ };
54
+ context?: {
55
+ provider: 'local';
56
+ };
57
+ review?: {
58
+ max_tokens?: number;
59
+ max_findings?: number;
60
+ };
61
+ }
62
+
63
+ // ─── Resolved config (global + repo merged, ready to use) ─────────────────────
64
+
65
+ export interface ResolvedConfig {
66
+ lang: 'en' | 'es';
67
+ providers: {
68
+ default: string;
69
+ fallback: string[];
70
+ agents: Record<string, string>;
71
+ };
72
+ claude: BuiltinProviderConfig;
73
+ openai: BuiltinProviderConfig;
74
+ gemini: BuiltinProviderConfig;
75
+ custom_providers: Record<string, CustomProviderConfig>;
76
+ review: { max_tokens: number; max_findings: number };
77
+ github: {
78
+ accountName: string;
79
+ token_env: string;
80
+ username?: string;
81
+ owner?: string;
82
+ repo?: string;
83
+ };
84
+ }
85
+
86
+ // ─── Domain types ─────────────────────────────────────────────────────────────
87
+
88
+ export interface AivRules {
89
+ sensitive_modules?: string[];
90
+ business_rules?: Record<string, {
91
+ required_calls?: string[];
92
+ required_checks?: string[];
93
+ forbidden_patterns?: string[];
94
+ }>;
95
+ }
96
+
97
+ export interface TreeNode {
98
+ path: string;
99
+ type: 'file' | 'directory';
100
+ module_type?: 'auth' | 'sql' | 'frontend' | 'backend' | 'infra' | 'config' | 'test' | 'other';
101
+ sensitivity?: 'low' | 'medium' | 'high';
102
+ children?: TreeNode[];
103
+ }
104
+
105
+ export interface PullRequest {
106
+ id: number;
107
+ number: number;
108
+ title: string;
109
+ author: string;
110
+ branch: string;
111
+ base: string;
112
+ url: string;
113
+ state: string;
114
+ createdAt: string;
115
+ updatedAt: string;
116
+ additions: number;
117
+ deletions: number;
118
+ changedFiles: number;
119
+ labels: string[];
120
+ description?: string;
121
+ }
122
+
123
+ export interface PRFile {
124
+ filename: string;
125
+ status: 'added' | 'modified' | 'deleted' | 'renamed';
126
+ additions: number;
127
+ deletions: number;
128
+ patch?: string;
129
+ }
130
+
131
+ export interface PRDiff {
132
+ pr: PullRequest;
133
+ files: PRFile[];
134
+ rawDiff: string;
135
+ }
136
+
137
+ export interface AgentFinding {
138
+ severity: 'critical' | 'high' | 'medium' | 'low' | 'info';
139
+ category: string;
140
+ title: string;
141
+ description: string;
142
+ file?: string;
143
+ suggestion?: string;
144
+ }
145
+
146
+ export interface AgentResult {
147
+ agentName: string;
148
+ findings: AgentFinding[];
149
+ summary: string;
150
+ riskScore: number;
151
+ }
152
+
153
+ export interface ReviewResult {
154
+ prNumber: number;
155
+ prTitle: string;
156
+ executiveSummary: string;
157
+ riskScore: number;
158
+ riskLabel: 'LOW' | 'MEDIUM' | 'HIGH' | 'CRITICAL';
159
+ agents: AgentResult[];
160
+ businessRisks: AgentFinding[];
161
+ architectureIssues: AgentFinding[];
162
+ securityIssues: AgentFinding[];
163
+ possibleRegressions: string[];
164
+ generatedAt: string;
165
+ }
166
+
167
+ export interface ProjectContext {
168
+ architecture: string;
169
+ modules: string[];
170
+ technologies: string[];
171
+ criticalDependencies: string[];
172
+ sensitiveZones: string[];
173
+ businessRules: string[];
174
+ systemSummary: string;
175
+ }
package/tsconfig.json ADDED
@@ -0,0 +1,17 @@
1
+ {
2
+ "compilerOptions": {
3
+ "target": "ES2022",
4
+ "module": "commonjs",
5
+ "lib": ["ES2022"],
6
+ "outDir": "./dist",
7
+ "rootDir": "./src",
8
+ "strict": true,
9
+ "esModuleInterop": true,
10
+ "skipLibCheck": true,
11
+ "forceConsistentCasingInFileNames": true,
12
+ "resolveJsonModule": true,
13
+ "noEmit": true
14
+ },
15
+ "include": ["src/**/*"],
16
+ "exclude": ["node_modules", "dist"]
17
+ }
package/tsup.config.ts ADDED
@@ -0,0 +1,12 @@
1
+ import { defineConfig } from 'tsup';
2
+
3
+ export default defineConfig({
4
+ entry: ['src/index.ts'],
5
+ format: ['cjs'],
6
+ target: 'node18',
7
+ minify: true,
8
+ clean: true,
9
+ splitting: false,
10
+ sourcemap: false,
11
+ dts: false,
12
+ });