@ariso-ai/ivan 1.0.25 → 1.0.28

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 (46) hide show
  1. package/dist/config.js +11 -11
  2. package/dist/config.js.map +1 -1
  3. package/dist/database/migrations/016_create_reviews_table.d.ts +3 -0
  4. package/dist/database/migrations/016_create_reviews_table.d.ts.map +1 -0
  5. package/dist/database/migrations/016_create_reviews_table.js +19 -0
  6. package/dist/database/migrations/016_create_reviews_table.js.map +1 -0
  7. package/dist/database/migrations/016_create_session_analyses_table.d.ts +3 -0
  8. package/dist/database/migrations/016_create_session_analyses_table.d.ts.map +1 -0
  9. package/dist/database/migrations/016_create_session_analyses_table.js +19 -0
  10. package/dist/database/migrations/016_create_session_analyses_table.js.map +1 -0
  11. package/dist/database/migrations/index.d.ts.map +1 -1
  12. package/dist/database/migrations/index.js +3 -1
  13. package/dist/database/migrations/index.js.map +1 -1
  14. package/dist/database.d.ts +2 -0
  15. package/dist/database.d.ts.map +1 -1
  16. package/dist/database.js +3 -0
  17. package/dist/database.js.map +1 -1
  18. package/dist/index.js +4 -2
  19. package/dist/index.js.map +1 -1
  20. package/dist/learnings/coding-sessions-command.d.ts +12 -0
  21. package/dist/learnings/coding-sessions-command.d.ts.map +1 -0
  22. package/dist/learnings/coding-sessions-command.js +274 -0
  23. package/dist/learnings/coding-sessions-command.js.map +1 -0
  24. package/dist/learnings/database.js +1 -1
  25. package/dist/learnings/database.js.map +1 -1
  26. package/dist/learnings/embeddings.d.ts.map +1 -1
  27. package/dist/learnings/embeddings.js +15 -2
  28. package/dist/learnings/embeddings.js.map +1 -1
  29. package/dist/learnings/index.d.ts +1 -1
  30. package/dist/learnings/index.d.ts.map +1 -1
  31. package/dist/learnings/index.js +23 -11
  32. package/dist/learnings/index.js.map +1 -1
  33. package/dist/learnings/install-hooks-command.js +2 -2
  34. package/dist/learnings/session-analyzer.d.ts +39 -0
  35. package/dist/learnings/session-analyzer.d.ts.map +1 -0
  36. package/dist/learnings/session-analyzer.js +339 -0
  37. package/dist/learnings/session-analyzer.js.map +1 -0
  38. package/dist/learnings/session-parser.d.ts +46 -0
  39. package/dist/learnings/session-parser.d.ts.map +1 -0
  40. package/dist/learnings/session-parser.js +235 -0
  41. package/dist/learnings/session-parser.js.map +1 -0
  42. package/dist/services/review-executor.d.ts +8 -0
  43. package/dist/services/review-executor.d.ts.map +1 -0
  44. package/dist/services/review-executor.js +159 -0
  45. package/dist/services/review-executor.js.map +1 -0
  46. package/package.json +2 -2
@@ -0,0 +1,159 @@
1
+ import { execSync } from 'child_process';
2
+ import chalk from 'chalk';
3
+ import { randomUUID } from 'crypto';
4
+ import { DatabaseManager } from '../database.js';
5
+ import { ExecutorFactory } from './executor-factory.js';
6
+ export class ReviewExecutor {
7
+ dbManager;
8
+ constructor() {
9
+ this.dbManager = new DatabaseManager();
10
+ }
11
+ async executeReviews(prNumbers) {
12
+ const workingDir = process.cwd();
13
+ console.log(chalk.blue.bold(`🔍 Reviewing ${prNumbers.length} PR(s)...`));
14
+ console.log('');
15
+ for (const prNumber of prNumbers) {
16
+ await this.reviewPR(prNumber, workingDir);
17
+ console.log('');
18
+ }
19
+ this.dbManager.close();
20
+ console.log(chalk.green.bold('✅ All reviews completed!'));
21
+ console.log(chalk.gray('Run "ivan web" to view reviews in the dashboard.'));
22
+ }
23
+ async reviewPR(prNumber, workingDir) {
24
+ const db = this.dbManager.getKysely();
25
+ const now = new Date().toISOString();
26
+ const reviewUuid = randomUUID();
27
+ console.log(chalk.blue(`📋 Reviewing PR #${prNumber}...`));
28
+ // Fetch PR metadata
29
+ let prUrl = null;
30
+ let prTitle = null;
31
+ let repositoryId = null;
32
+ try {
33
+ const prJson = execSync(`gh pr view ${prNumber} --json number,title,url`, { cwd: workingDir, encoding: 'utf-8' });
34
+ const pr = JSON.parse(prJson);
35
+ prUrl = pr.url;
36
+ prTitle = pr.title;
37
+ console.log(chalk.gray(` Title: ${prTitle}`));
38
+ console.log(chalk.gray(` URL: ${prUrl}`));
39
+ }
40
+ catch (error) {
41
+ console.error(chalk.red(`❌ Failed to fetch PR #${prNumber} metadata:`), error);
42
+ }
43
+ // Look up repository_id from the DB
44
+ try {
45
+ const remoteUrl = execSync('git config --get remote.origin.url', {
46
+ cwd: workingDir,
47
+ encoding: 'utf-8'
48
+ }).trim();
49
+ const repo = await db
50
+ .selectFrom('repositories')
51
+ .select('id')
52
+ .where('remote_url', '=', remoteUrl)
53
+ .executeTakeFirst();
54
+ if (repo)
55
+ repositoryId = repo.id;
56
+ }
57
+ catch {
58
+ // Ignore — repository may not be registered
59
+ }
60
+ // Create the review record as 'running'
61
+ await db
62
+ .insertInto('reviews')
63
+ .values({
64
+ uuid: reviewUuid,
65
+ pr_number: prNumber,
66
+ pr_url: prUrl,
67
+ pr_title: prTitle,
68
+ repository_id: repositoryId,
69
+ status: 'running',
70
+ review_content: null,
71
+ execution_log: null,
72
+ created_at: now,
73
+ updated_at: now
74
+ })
75
+ .execute();
76
+ // Build the review prompt using the PR diff
77
+ let prDiff = '';
78
+ let prFiles = '';
79
+ try {
80
+ prDiff = execSync(`gh pr diff ${prNumber}`, {
81
+ cwd: workingDir,
82
+ encoding: 'utf-8',
83
+ maxBuffer: 10 * 1024 * 1024
84
+ });
85
+ }
86
+ catch (error) {
87
+ console.warn(chalk.yellow(` ⚠️ Could not fetch diff for PR #${prNumber}`));
88
+ }
89
+ try {
90
+ prFiles = execSync(`gh pr view ${prNumber} --json files --jq '.files[].path'`, { cwd: workingDir, encoding: 'utf-8' });
91
+ }
92
+ catch {
93
+ // Ignore
94
+ }
95
+ const prompt = `You are a senior software engineer performing a thorough code review of PR #${prNumber}.
96
+
97
+ ${prTitle ? `PR Title: ${prTitle}` : ''}
98
+ ${prUrl ? `PR URL: ${prUrl}` : ''}
99
+ ${prFiles ? `\nChanged files:\n${prFiles}` : ''}
100
+
101
+ ${prDiff ? `\nDiff:\n\`\`\`diff\n${prDiff}\n\`\`\`` : 'No diff available — review the PR branch directly.'}
102
+
103
+ Please review this pull request and provide:
104
+ 1. A brief summary of what the PR does
105
+ 2. Potential bugs or logic errors
106
+ 3. Security concerns (if any)
107
+ 4. Code quality and maintainability issues
108
+ 5. Suggestions for improvement
109
+ 6. Overall verdict: Approve / Request Changes / Comment
110
+
111
+ Format your review clearly with sections and be specific about file and line references where applicable.
112
+ After completing your review, output the final review as plain text starting with the line: "## Code Review: PR #${prNumber}"`;
113
+ try {
114
+ const executor = ExecutorFactory.getExecutor();
115
+ executor.quietMode = false;
116
+ const { log, lastMessage } = await executor.executeTask(prompt, workingDir);
117
+ // Extract the review content from the last message or log
118
+ const reviewContent = this.extractReviewContent(lastMessage, log, prNumber);
119
+ await db
120
+ .updateTable('reviews')
121
+ .set({
122
+ status: 'completed',
123
+ review_content: reviewContent,
124
+ execution_log: log,
125
+ updated_at: new Date().toISOString()
126
+ })
127
+ .where('uuid', '=', reviewUuid)
128
+ .execute();
129
+ console.log(chalk.green(` ✅ Review for PR #${prNumber} completed.`));
130
+ }
131
+ catch (error) {
132
+ const errorMsg = error instanceof Error ? error.message : String(error);
133
+ await db
134
+ .updateTable('reviews')
135
+ .set({
136
+ status: 'failed',
137
+ execution_log: errorMsg,
138
+ updated_at: new Date().toISOString()
139
+ })
140
+ .where('uuid', '=', reviewUuid)
141
+ .execute();
142
+ console.error(chalk.red(` ❌ Review for PR #${prNumber} failed: ${errorMsg}`));
143
+ }
144
+ }
145
+ extractReviewContent(lastMessage, log, prNumber) {
146
+ const marker = `## Code Review: PR #${prNumber}`;
147
+ // Try to find the structured review in the last message first
148
+ const inLast = lastMessage.indexOf(marker);
149
+ if (inLast !== -1)
150
+ return lastMessage.slice(inLast);
151
+ // Fall back to scanning the execution log
152
+ const inLog = log.indexOf(marker);
153
+ if (inLog !== -1)
154
+ return log.slice(inLog);
155
+ // If Claude didn't use the marker, return the last message as-is
156
+ return lastMessage || log;
157
+ }
158
+ }
159
+ //# sourceMappingURL=review-executor.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"review-executor.js","sourceRoot":"","sources":["../../src/services/review-executor.ts"],"names":[],"mappings":"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"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@ariso-ai/ivan",
3
- "version": "1.0.25",
3
+ "version": "1.0.28",
4
4
  "type": "module",
5
5
  "main": "dist/index.js",
6
6
  "bin": {
@@ -73,6 +73,6 @@
73
73
  "kysely": "^0.28.5",
74
74
  "openai": "^5.16.0",
75
75
  "ora": "^8.2.0",
76
- "sqlite-vec": "^0.1.7"
76
+ "sqlite-vec": "^0.1.9"
77
77
  }
78
78
  }