scai 0.1.80 → 0.1.82

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/README.md CHANGED
@@ -149,15 +149,22 @@ SCAI supports an integrated review flow for GitHub pull requests. To get started
149
149
 
150
150
  ```sh
151
151
  $ scai git review -a
152
- šŸ” Fetching pull requests and diffs...
153
152
  šŸ“¦ Resolving GitHub repo info from indexDir: ./
154
153
  šŸ”— Git origin URL: git@github.com:org/repo.git
155
154
  āœ… Parsed: owner='org', repo='repo'
156
- šŸ‘¤ Authenticated user: username
155
+ šŸ‘¤ Authenticated user: dev-user123
156
+
157
+ šŸ” Fetching pull requests and diffs...
158
+ āœ… Fetched 5 PR(s) with diffs.
157
159
 
158
160
  šŸ“¦ Open Pull Requests with review requested:
159
- 1) #123 - Fix login timeout bug
160
- 2) #122 - Upgrade dependencies
161
+ | # | ID | TITLE | AUTHOR | STATUS | CREATED | REVIEWERS | REVIEWS |
162
+ | - | ---- | ----------------------------- | ---------- | ------ | ---------- | ----------------------------- | ------------------- |
163
+ | 1 | #120 | fix/session-timeout | dev-alice | Open | 2025-08-08 | code-analyzer\[bot], dev-bob | āœ… Approved |
164
+ | 2 | #118 | feature/1482-support-wfs2 | dev-carol | Open | 2025-08-07 | code-analyzer\[bot], dev-dave | āœ… Approved |
165
+ | 3 | #117 | refactor/win-server-support | dev-erin | Open | 2025-08-06 | dev-frank, dev-alice | āŒ Changes Requested |
166
+ | 4 | #114 | bump/vue-i18n-9.14.5 | dependabot | Open | 2025-08-04 | code-analyzer\[bot] | āœ… Approved |
167
+ | 5 | #113 | bugfix/null-navigator-check | dev-bob | Open | 2025-08-03 | dev-alice, dev-carol | āœ… Approved |
161
168
 
162
169
  šŸ‘‰ Choose a PR to review [1-2]: 1
163
170
  āœ… Model response received.
@@ -85,11 +85,21 @@ function askUserToPickPR(prs) {
85
85
  const rows = prs.map((pr, i) => ({
86
86
  '#': i + 1,
87
87
  ID: `#${pr.number}`,
88
- Title: truncate(pr.title, 50),
89
- Author: pr.user || '—',
88
+ Title: chalk.gray(truncate(pr.title, 50)),
89
+ Author: chalk.magentaBright(pr.user || '—'),
90
90
  Status: pr.draft ? 'Draft' : 'Open',
91
91
  Created: pr.created_at?.split('T')[0] || '',
92
- Reviewers: pr.requested_reviewers?.map(r => r.login).join(', ') || '—',
92
+ 'Requested Reviewers': pr.requested_reviewers?.length
93
+ ? pr.requested_reviewers.join(', ')
94
+ : chalk.gray('—'),
95
+ 'Actual Reviewers': pr.reviewers?.length
96
+ ? chalk.cyan(pr.reviewers.join(', '))
97
+ : chalk.gray('—'),
98
+ Reviews: pr.review_status === 'Approved'
99
+ ? chalk.green('Approved')
100
+ : pr.review_status === 'Changes Requested'
101
+ ? chalk.red('Changes Requested')
102
+ : chalk.gray('—'),
93
103
  }));
94
104
  console.log(chalk.blue("\nšŸ“¦ Open Pull Requests:"));
95
105
  console.log(columnify(rows, {
@@ -97,7 +107,9 @@ function askUserToPickPR(prs) {
97
107
  headingTransform: (h) => chalk.cyan(h.toUpperCase()),
98
108
  config: {
99
109
  Title: { maxWidth: 50 },
100
- Reviewers: { maxWidth: 30 }
110
+ 'Requested Reviewers': { maxWidth: 30 },
111
+ 'Actual Reviewers': { maxWidth: 30 },
112
+ Reviews: { maxWidth: 20 },
101
113
  }
102
114
  }));
103
115
  const rl = readline.createInterface({ input: process.stdin, output: process.stdout });
@@ -18,11 +18,20 @@ export async function summarizeFile(filepath) {
18
18
  if (matches.length > 0) {
19
19
  const topMatch = matches[0];
20
20
  filePathResolved = path.resolve(process.cwd(), topMatch.path);
21
- console.log(`šŸ”— Matched file: ${path.relative(process.cwd(), filePathResolved)}`);
21
+ console.log(`šŸ”— Matched file from index: ${path.relative(process.cwd(), filePathResolved)}`);
22
22
  }
23
23
  else {
24
- console.error(`āŒ Could not resolve file from query: "${filepath}"`);
25
- return;
24
+ // Fallback: check if it's a real file in CWD
25
+ const localPath = path.resolve(process.cwd(), filepath);
26
+ try {
27
+ await fs.access(localPath);
28
+ filePathResolved = localPath;
29
+ console.log(`šŸ“ Using local file: ${path.relative(process.cwd(), localPath)}`);
30
+ }
31
+ catch {
32
+ console.error(`āŒ Could not find or resolve file: "${filepath}"`);
33
+ return;
34
+ }
26
35
  }
27
36
  }
28
37
  // šŸ“„ Load file content from resolved path
@@ -12,16 +12,45 @@ export async function fetchOpenPullRequests(token, owner, repo) {
12
12
  throw new Error(`GitHub API error: ${res.status} ${res.statusText}`);
13
13
  }
14
14
  const prs = await res.json();
15
- return prs.map((pr) => ({
16
- number: pr.number,
17
- title: pr.title,
18
- url: pr.url,
19
- diff_url: pr.diff_url,
20
- draft: pr.draft,
21
- merged_at: pr.merged_at,
22
- base: pr.base,
23
- requested_reviewers: pr.requested_reviewers,
15
+ const augmentedPRs = await Promise.all(prs.map(async (pr) => {
16
+ const reviewsRes = await fetch(`${pr.url}/reviews`, {
17
+ headers: {
18
+ Authorization: `token ${token}`,
19
+ Accept: 'application/vnd.github.v3+json',
20
+ }
21
+ });
22
+ let latestState = '—';
23
+ let reviewers = [];
24
+ if (reviewsRes.ok) {
25
+ const reviews = await reviewsRes.json();
26
+ const latestPerUser = new Map();
27
+ for (const review of reviews) {
28
+ latestPerUser.set(review.user.login, review.state);
29
+ }
30
+ reviewers = [...latestPerUser.keys()]; // āœ… actual reviewers
31
+ if ([...latestPerUser.values()].includes('CHANGES_REQUESTED')) {
32
+ latestState = 'Changes Requested';
33
+ }
34
+ else if ([...latestPerUser.values()].includes('APPROVED')) {
35
+ latestState = 'Approved';
36
+ }
37
+ }
38
+ return {
39
+ number: pr.number,
40
+ title: pr.title,
41
+ url: pr.url,
42
+ diff_url: pr.diff_url,
43
+ draft: pr.draft,
44
+ merged_at: pr.merged_at,
45
+ base: pr.base,
46
+ user: pr.user?.login || 'unknown',
47
+ created_at: pr.created_at,
48
+ requested_reviewers: pr.requested_reviewers?.map((r) => r.login) || [],
49
+ reviewers,
50
+ review_status: latestState,
51
+ };
24
52
  }));
53
+ return augmentedPRs;
25
54
  }
26
55
  export async function getGitHubUsername(token) {
27
56
  const res = await fetch('https://api.github.com/user', {
@@ -1,13 +1,14 @@
1
1
  import columnify from "columnify";
2
2
  export function styleOutput(summaryText) {
3
3
  const terminalWidth = process.stdout.columns || 80;
4
- // You can control wrapping here
5
- const formatted = columnify([{ Summary: summaryText }], {
4
+ // Split by line to simulate multiple rows instead of one long wrapped field
5
+ const lines = summaryText.trim().split('\n').map(line => ({ Summary: line }));
6
+ const formatted = columnify(lines, {
6
7
  columnSplitter: ' ',
7
8
  maxLineWidth: terminalWidth,
8
9
  config: {
9
10
  Summary: {
10
- maxWidth: Math.floor((terminalWidth * 2) / 3), // Use 2/3 width like before
11
+ maxWidth: Math.floor((terminalWidth * 2) / 3),
11
12
  align: "left",
12
13
  },
13
14
  },
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "scai",
3
- "version": "0.1.80",
3
+ "version": "0.1.82",
4
4
  "type": "module",
5
5
  "bin": {
6
6
  "scai": "./dist/index.js"