pierre-review 0.1.88 → 0.1.89
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/dist/db/queries.js +266 -6
- package/dist/pro/bind.js +2 -0
- package/package.json +1 -1
- package/public/assets/{AiFixTab-xunM4Dcn.js → AiFixTab-p6wYqjXd.js} +1 -1
- package/public/assets/{ClaudeReviewTab-BSbuovsJ.js → ClaudeReviewTab-DGxiNG7d.js} +1 -1
- package/public/assets/{PrBotBehaviourTab-DiMPFSk-.js → PrBotBehaviourTab-BrlRXlV3.js} +1 -1
- package/public/assets/index-CtLmjyuw.css +1 -0
- package/public/assets/index-XM1NIyvh.js +54 -0
- package/public/index.html +2 -2
- package/public/assets/index-FNWDcDl6.js +0 -54
- package/public/assets/index-eMcv5bjI.css +0 -1
package/dist/db/queries.js
CHANGED
|
@@ -6104,12 +6104,272 @@ opts) {
|
|
|
6104
6104
|
}
|
|
6105
6105
|
return out;
|
|
6106
6106
|
}
|
|
6107
|
-
|
|
6108
|
-
|
|
6109
|
-
|
|
6110
|
-
|
|
6111
|
-
|
|
6112
|
-
|
|
6107
|
+
export async function getHumanReviewComments(accountId, window, scopeRepoIds) {
|
|
6108
|
+
if (scopeRepoIds != null && scopeRepoIds.length === 0)
|
|
6109
|
+
return { comments: [], truncated: false };
|
|
6110
|
+
const automatedIds = await automatedReviewerUserIds(accountId);
|
|
6111
|
+
const nowMs = Date.now();
|
|
6112
|
+
const windowDays = window === 'rolling_7' ? 7 : window === 'rolling_30' ? 30 : 14;
|
|
6113
|
+
const from = new Date(nowMs - windowDays * 86_400_000);
|
|
6114
|
+
const repoScopeFilter = scopeRepoIds != null ? [inArray(pullRequests.repoId, scopeRepoIds)] : [];
|
|
6115
|
+
// Exclude bots two ways: any is_bot user, and the resolved automated-reviewer set (which can
|
|
6116
|
+
// include service-account PATs that carry is_bot=false). notInArray on [] is a no-op we skip.
|
|
6117
|
+
const excludeAutomated = automatedIds.length > 0 ? [notInArray(reviewComments.authorId, automatedIds)] : [];
|
|
6118
|
+
const excludeAutomatedPr = automatedIds.length > 0 ? [notInArray(prComments.authorId, automatedIds)] : [];
|
|
6119
|
+
const reviewRows = await db
|
|
6120
|
+
.select({
|
|
6121
|
+
id: reviewComments.id,
|
|
6122
|
+
prId: reviewComments.prId,
|
|
6123
|
+
prNumber: pullRequests.number,
|
|
6124
|
+
repoId: pullRequests.repoId,
|
|
6125
|
+
owner: repos.owner,
|
|
6126
|
+
name: repos.name,
|
|
6127
|
+
authorId: reviewComments.authorId,
|
|
6128
|
+
login: users.githubLogin,
|
|
6129
|
+
displayName: users.displayName,
|
|
6130
|
+
body: reviewComments.body,
|
|
6131
|
+
createdAt: reviewComments.createdAt,
|
|
6132
|
+
path: reviewThreads.path,
|
|
6133
|
+
derivedState: reviewThreads.derivedState,
|
|
6134
|
+
threadId: reviewComments.threadId,
|
|
6135
|
+
})
|
|
6136
|
+
.from(reviewComments)
|
|
6137
|
+
.innerJoin(pullRequests, eq(pullRequests.id, reviewComments.prId))
|
|
6138
|
+
.innerJoin(repos, eq(repos.id, pullRequests.repoId))
|
|
6139
|
+
.innerJoin(users, eq(users.id, reviewComments.authorId))
|
|
6140
|
+
.leftJoin(reviewThreads, eq(reviewThreads.id, reviewComments.threadId))
|
|
6141
|
+
.where(and(eq(pullRequests.accountId, accountId), eq(users.isBot, false), gte(reviewComments.createdAt, from), ...excludeAutomated, ...repoScopeFilter))
|
|
6142
|
+
.orderBy(desc(reviewComments.createdAt))
|
|
6143
|
+
.limit(BOT_THEME_COMMENT_CAP)
|
|
6144
|
+
.execute();
|
|
6145
|
+
const prCommentRows = await db
|
|
6146
|
+
.select({
|
|
6147
|
+
id: prComments.id,
|
|
6148
|
+
prId: prComments.prId,
|
|
6149
|
+
prNumber: pullRequests.number,
|
|
6150
|
+
repoId: pullRequests.repoId,
|
|
6151
|
+
owner: repos.owner,
|
|
6152
|
+
name: repos.name,
|
|
6153
|
+
authorId: prComments.authorId,
|
|
6154
|
+
login: users.githubLogin,
|
|
6155
|
+
displayName: users.displayName,
|
|
6156
|
+
body: prComments.body,
|
|
6157
|
+
createdAt: prComments.createdAt,
|
|
6158
|
+
})
|
|
6159
|
+
.from(prComments)
|
|
6160
|
+
.innerJoin(pullRequests, eq(pullRequests.id, prComments.prId))
|
|
6161
|
+
.innerJoin(repos, eq(repos.id, pullRequests.repoId))
|
|
6162
|
+
.innerJoin(users, eq(users.id, prComments.authorId))
|
|
6163
|
+
.where(and(eq(pullRequests.accountId, accountId), eq(users.isBot, false), gte(prComments.createdAt, from), ...excludeAutomatedPr, ...repoScopeFilter))
|
|
6164
|
+
.orderBy(desc(prComments.createdAt))
|
|
6165
|
+
.limit(BOT_THEME_COMMENT_CAP)
|
|
6166
|
+
.execute();
|
|
6167
|
+
const toIso = (d) => {
|
|
6168
|
+
if (d == null)
|
|
6169
|
+
return new Date(0).toISOString();
|
|
6170
|
+
if (d instanceof Date)
|
|
6171
|
+
return d.toISOString();
|
|
6172
|
+
const ms = Number(d) > 1e12 ? Number(d) : Number(d) * 1000;
|
|
6173
|
+
return new Date(ms).toISOString();
|
|
6174
|
+
};
|
|
6175
|
+
const out = [];
|
|
6176
|
+
for (const r of reviewRows) {
|
|
6177
|
+
if (r.authorId == null)
|
|
6178
|
+
continue;
|
|
6179
|
+
out.push({
|
|
6180
|
+
id: r.id,
|
|
6181
|
+
source: 'review',
|
|
6182
|
+
prId: r.prId,
|
|
6183
|
+
prNumber: r.prNumber,
|
|
6184
|
+
repoId: r.repoId,
|
|
6185
|
+
repoFullName: `${r.owner}/${r.name}`,
|
|
6186
|
+
path: r.path ?? null,
|
|
6187
|
+
authorUserId: r.authorId,
|
|
6188
|
+
login: r.login ?? null,
|
|
6189
|
+
displayName: r.displayName ?? null,
|
|
6190
|
+
body: r.body,
|
|
6191
|
+
createdAt: toIso(r.createdAt),
|
|
6192
|
+
derivedState: r.derivedState ?? null,
|
|
6193
|
+
threadId: r.threadId ?? null,
|
|
6194
|
+
});
|
|
6195
|
+
}
|
|
6196
|
+
for (const r of prCommentRows) {
|
|
6197
|
+
if (r.authorId == null)
|
|
6198
|
+
continue;
|
|
6199
|
+
out.push({
|
|
6200
|
+
id: r.id,
|
|
6201
|
+
source: 'issue',
|
|
6202
|
+
prId: r.prId,
|
|
6203
|
+
prNumber: r.prNumber,
|
|
6204
|
+
repoId: r.repoId,
|
|
6205
|
+
repoFullName: `${r.owner}/${r.name}`,
|
|
6206
|
+
path: null,
|
|
6207
|
+
authorUserId: r.authorId,
|
|
6208
|
+
login: r.login ?? null,
|
|
6209
|
+
displayName: r.displayName ?? null,
|
|
6210
|
+
body: r.body,
|
|
6211
|
+
createdAt: toIso(r.createdAt),
|
|
6212
|
+
derivedState: null,
|
|
6213
|
+
threadId: null,
|
|
6214
|
+
});
|
|
6215
|
+
}
|
|
6216
|
+
out.sort((a, b) => (a.createdAt < b.createdAt ? 1 : a.createdAt > b.createdAt ? -1 : 0));
|
|
6217
|
+
const truncated = reviewRows.length >= BOT_THEME_COMMENT_CAP ||
|
|
6218
|
+
prCommentRows.length >= BOT_THEME_COMMENT_CAP ||
|
|
6219
|
+
out.length > BOT_THEME_COMMENT_CAP;
|
|
6220
|
+
return { comments: out.slice(0, BOT_THEME_COMMENT_CAP), truncated };
|
|
6221
|
+
}
|
|
6222
|
+
const BOT_THEME_COMMENT_CAP = 3000; // most-recent bot comments per source considered for a summary
|
|
6223
|
+
export async function getBotReviewComments(accountId, window, scopeRepoIds) {
|
|
6224
|
+
// Team scope resolved to no repos → nothing to summarize.
|
|
6225
|
+
if (scopeRepoIds != null && scopeRepoIds.length === 0)
|
|
6226
|
+
return { comments: [], truncated: false };
|
|
6227
|
+
const automatedIds = await automatedReviewerUserIds(accountId);
|
|
6228
|
+
if (automatedIds.length === 0)
|
|
6229
|
+
return { comments: [], truncated: false };
|
|
6230
|
+
const kindMap = await classificationKindForUser(accountId);
|
|
6231
|
+
const nowMs = Date.now();
|
|
6232
|
+
// Window resolution mirrors getBotAnalytics exactly (rolling_14 / 'sprint' both → 14d trailing).
|
|
6233
|
+
const windowDays = window === 'rolling_7' ? 7 : window === 'rolling_30' ? 30 : 14;
|
|
6234
|
+
const from = new Date(nowMs - windowDays * 86_400_000);
|
|
6235
|
+
const repoScopeFilter = scopeRepoIds != null ? [inArray(pullRequests.repoId, scopeRepoIds)] : [];
|
|
6236
|
+
// Per-reviewer label (custom classification label → vendor pretty name → login) — mirrors
|
|
6237
|
+
// getBotAnalytics.reviewerLabel exactly, so a bot reads the same here as in the ROI panel.
|
|
6238
|
+
const classLabel = new Map();
|
|
6239
|
+
for (const r of await db
|
|
6240
|
+
.select({ id: botReviewClassification.authorUserId, label: botReviewClassification.label })
|
|
6241
|
+
.from(botReviewClassification)
|
|
6242
|
+
.where(eq(botReviewClassification.accountId, accountId))
|
|
6243
|
+
.execute()) {
|
|
6244
|
+
if (r.label != null && r.label.trim() !== '')
|
|
6245
|
+
classLabel.set(r.id, r.label.trim());
|
|
6246
|
+
}
|
|
6247
|
+
const loginById = new Map();
|
|
6248
|
+
const rawLoginById = new Map();
|
|
6249
|
+
for (const r of await db
|
|
6250
|
+
.select({ id: users.id, login: users.githubLogin, name: users.displayName })
|
|
6251
|
+
.from(users)
|
|
6252
|
+
.where(inArray(users.id, automatedIds))
|
|
6253
|
+
.execute()) {
|
|
6254
|
+
loginById.set(r.id, r.name?.trim() || r.login || `#${r.id}`);
|
|
6255
|
+
if (r.login)
|
|
6256
|
+
rawLoginById.set(r.id, r.login);
|
|
6257
|
+
}
|
|
6258
|
+
const labelFor = (userId, kind) => {
|
|
6259
|
+
const custom = classLabel.get(userId);
|
|
6260
|
+
if (custom)
|
|
6261
|
+
return custom;
|
|
6262
|
+
if (kind !== 'in_house' && kind !== 'pierre' && kind !== 'vendor')
|
|
6263
|
+
return labelForKind(kind);
|
|
6264
|
+
return loginById.get(userId) ?? labelForKind(kind);
|
|
6265
|
+
};
|
|
6266
|
+
// Inline review-thread comments (carry the thread's path + derivedState).
|
|
6267
|
+
const reviewRows = await db
|
|
6268
|
+
.select({
|
|
6269
|
+
id: reviewComments.id,
|
|
6270
|
+
prId: reviewComments.prId,
|
|
6271
|
+
prNumber: pullRequests.number,
|
|
6272
|
+
repoId: pullRequests.repoId,
|
|
6273
|
+
owner: repos.owner,
|
|
6274
|
+
name: repos.name,
|
|
6275
|
+
authorId: reviewComments.authorId,
|
|
6276
|
+
body: reviewComments.body,
|
|
6277
|
+
createdAt: reviewComments.createdAt,
|
|
6278
|
+
path: reviewThreads.path,
|
|
6279
|
+
derivedState: reviewThreads.derivedState,
|
|
6280
|
+
threadId: reviewComments.threadId,
|
|
6281
|
+
})
|
|
6282
|
+
.from(reviewComments)
|
|
6283
|
+
.innerJoin(pullRequests, eq(pullRequests.id, reviewComments.prId))
|
|
6284
|
+
.innerJoin(repos, eq(repos.id, pullRequests.repoId))
|
|
6285
|
+
.leftJoin(reviewThreads, eq(reviewThreads.id, reviewComments.threadId))
|
|
6286
|
+
.where(and(eq(pullRequests.accountId, accountId), inArray(reviewComments.authorId, automatedIds), gte(reviewComments.createdAt, from), ...repoScopeFilter))
|
|
6287
|
+
.orderBy(desc(reviewComments.createdAt))
|
|
6288
|
+
.limit(BOT_THEME_COMMENT_CAP)
|
|
6289
|
+
.execute();
|
|
6290
|
+
// Issue-level PR comments (no path / derivedState).
|
|
6291
|
+
const prCommentRows = await db
|
|
6292
|
+
.select({
|
|
6293
|
+
id: prComments.id,
|
|
6294
|
+
prId: prComments.prId,
|
|
6295
|
+
prNumber: pullRequests.number,
|
|
6296
|
+
repoId: pullRequests.repoId,
|
|
6297
|
+
owner: repos.owner,
|
|
6298
|
+
name: repos.name,
|
|
6299
|
+
authorId: prComments.authorId,
|
|
6300
|
+
body: prComments.body,
|
|
6301
|
+
createdAt: prComments.createdAt,
|
|
6302
|
+
})
|
|
6303
|
+
.from(prComments)
|
|
6304
|
+
.innerJoin(pullRequests, eq(pullRequests.id, prComments.prId))
|
|
6305
|
+
.innerJoin(repos, eq(repos.id, pullRequests.repoId))
|
|
6306
|
+
.where(and(eq(pullRequests.accountId, accountId), inArray(prComments.authorId, automatedIds), gte(prComments.createdAt, from), ...repoScopeFilter))
|
|
6307
|
+
.orderBy(desc(prComments.createdAt))
|
|
6308
|
+
.limit(BOT_THEME_COMMENT_CAP)
|
|
6309
|
+
.execute();
|
|
6310
|
+
const toIso = (d) => {
|
|
6311
|
+
if (d == null)
|
|
6312
|
+
return new Date(0).toISOString();
|
|
6313
|
+
if (d instanceof Date)
|
|
6314
|
+
return d.toISOString();
|
|
6315
|
+
const ms = Number(d) > 1e12 ? Number(d) : Number(d) * 1000;
|
|
6316
|
+
return new Date(ms).toISOString();
|
|
6317
|
+
};
|
|
6318
|
+
const out = [];
|
|
6319
|
+
for (const r of reviewRows) {
|
|
6320
|
+
if (r.authorId == null)
|
|
6321
|
+
continue;
|
|
6322
|
+
const kind = kindMap.get(r.authorId) ?? 'in_house';
|
|
6323
|
+
out.push({
|
|
6324
|
+
id: r.id,
|
|
6325
|
+
source: 'review',
|
|
6326
|
+
prId: r.prId,
|
|
6327
|
+
prNumber: r.prNumber,
|
|
6328
|
+
repoId: r.repoId,
|
|
6329
|
+
repoFullName: `${r.owner}/${r.name}`,
|
|
6330
|
+
path: r.path ?? null,
|
|
6331
|
+
authorUserId: r.authorId,
|
|
6332
|
+
reviewerKey: `u${r.authorId}`,
|
|
6333
|
+
label: labelFor(r.authorId, kind),
|
|
6334
|
+
login: rawLoginById.get(r.authorId) ?? null,
|
|
6335
|
+
kind,
|
|
6336
|
+
body: r.body,
|
|
6337
|
+
createdAt: toIso(r.createdAt),
|
|
6338
|
+
derivedState: r.derivedState ?? null,
|
|
6339
|
+
threadId: r.threadId ?? null,
|
|
6340
|
+
});
|
|
6341
|
+
}
|
|
6342
|
+
for (const r of prCommentRows) {
|
|
6343
|
+
if (r.authorId == null)
|
|
6344
|
+
continue;
|
|
6345
|
+
const kind = kindMap.get(r.authorId) ?? 'in_house';
|
|
6346
|
+
out.push({
|
|
6347
|
+
id: r.id,
|
|
6348
|
+
source: 'issue',
|
|
6349
|
+
prId: r.prId,
|
|
6350
|
+
prNumber: r.prNumber,
|
|
6351
|
+
repoId: r.repoId,
|
|
6352
|
+
repoFullName: `${r.owner}/${r.name}`,
|
|
6353
|
+
path: null,
|
|
6354
|
+
authorUserId: r.authorId,
|
|
6355
|
+
reviewerKey: `u${r.authorId}`,
|
|
6356
|
+
label: labelFor(r.authorId, kind),
|
|
6357
|
+
login: rawLoginById.get(r.authorId) ?? null,
|
|
6358
|
+
kind,
|
|
6359
|
+
body: r.body,
|
|
6360
|
+
createdAt: toIso(r.createdAt),
|
|
6361
|
+
derivedState: null,
|
|
6362
|
+
threadId: null,
|
|
6363
|
+
});
|
|
6364
|
+
}
|
|
6365
|
+
// Newest-first, capped combined (the plugin funnels further before the LLM). `truncated` when
|
|
6366
|
+
// either source hit its own cap OR the combined stream overflowed the cap.
|
|
6367
|
+
out.sort((a, b) => (a.createdAt < b.createdAt ? 1 : a.createdAt > b.createdAt ? -1 : 0));
|
|
6368
|
+
const truncated = reviewRows.length >= BOT_THEME_COMMENT_CAP ||
|
|
6369
|
+
prCommentRows.length >= BOT_THEME_COMMENT_CAP ||
|
|
6370
|
+
out.length > BOT_THEME_COMMENT_CAP;
|
|
6371
|
+
return { comments: out.slice(0, BOT_THEME_COMMENT_CAP), truncated };
|
|
6372
|
+
}
|
|
6113
6373
|
export async function getBotAnalytics(accountId, window,
|
|
6114
6374
|
// Team scope: null/undefined = all account repos; a repo-id list = only those; [] = no
|
|
6115
6375
|
// repos in scope (e.g. the "No team" scope with everything assigned) → empty analytics.
|
package/dist/pro/bind.js
CHANGED
|
@@ -93,6 +93,8 @@ export async function bindProPlugin(app) {
|
|
|
93
93
|
getTeamMetricsDetail: (accountId, window, repoIds) => hostQueries.getTeamMetricsDetail(accountId, window, repoIds),
|
|
94
94
|
getAiUsage: (accountId, sinceMs) => getAiUsageSummary(accountId, sinceMs),
|
|
95
95
|
getBotAnalytics: (accountId, window, repoIds) => hostQueries.getBotAnalytics(accountId, window, repoIds ?? null),
|
|
96
|
+
getBotReviewComments: (accountId, window, repoIds) => hostQueries.getBotReviewComments(accountId, window, repoIds ?? null),
|
|
97
|
+
getHumanReviewComments: (accountId, window, repoIds) => hostQueries.getHumanReviewComments(accountId, window, repoIds ?? null),
|
|
96
98
|
},
|
|
97
99
|
recordAiUsage: (row) => recordAiUsage(row),
|
|
98
100
|
aiCredits: {
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "pierre-review",
|
|
3
|
-
"version": "0.1.
|
|
3
|
+
"version": "0.1.89",
|
|
4
4
|
"description": "Dashboard for tracking your team's GitHub PR activity across repos — local (SQLite + gh) or self-hosted multi-tenant cloud (Postgres + GitHub App).",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"author": "Alex Wakeman",
|
|
@@ -1,3 +1,3 @@
|
|
|
1
|
-
import{r as o,j as e}from"./tanstack-R-s9abdD.js";import{I as te,z as W,A as re,c as ne,d as ae,v as ie,K as ce,N as J,M as K,k as le,o as oe,m as de,C as ue,b as xe,R as Q,a as he,p as X,F as Z,r as I,J as ge,O as me,s as be,q as pe,D as fe,l as Y}from"./index-
|
|
1
|
+
import{r as o,j as e}from"./tanstack-R-s9abdD.js";import{I as te,z as W,A as re,c as ne,d as ae,v as ie,K as ce,N as J,M as K,k as le,o as oe,m as de,C as ue,b as xe,R as Q,a as he,p as X,F as Z,r as I,J as ge,O as me,s as be,q as pe,D as fe,l as Y}from"./index-XM1NIyvh.js";import"./markdown-BUNN1sk6.js";import"./highlight-C8vPehS1.js";import"./vis-C3BCkP5U.js";const S="whitespace-nowrap rounded border border-blue-400 px-2.5 py-1 text-xs text-blue-600 hover:bg-blue-50 disabled:opacity-50 dark:border-blue-600 dark:text-blue-400 dark:hover:bg-blue-900/30",j="whitespace-nowrap rounded border border-gray-300 px-2.5 py-1 text-xs hover:border-gray-400 disabled:opacity-50 dark:border-gray-700 dark:hover:border-gray-500",ye={fetching_diff:"Reading the PR",cloning:"Checking out the code",fixing:"Applying the fix",capturing:"Capturing changes",persisting:"Saving"};function je(s){var t;if(!s||s.status==="idle")return null;if(s.status==="queued")return 6;const r=s.progress;if(!r)return 10;switch(r.phase){case"fetching_diff":return 12;case"cloning":return 28;case"fixing":return Math.min(90,45+(((t=r.recentActivity)==null?void 0:t.length)??0)*3);case"capturing":return 92;case"persisting":return 96;default:return 20}}const ke={cloning:"Checking out the code",applying_fix:"Applying the fix",fetching_trunk:"Fetching the trunk",rebasing:"Rebasing onto the trunk",merging:"Merging the trunk in",resolving_conflicts:"Resolving conflicts with Claude",verifying:"Verifying the result",pushing:"Pushing"};function Ne(s){var t;if(!s||s.status==="idle")return null;if(s.status==="queued")return 6;const r=s.progress;if(!r)return 10;switch(r.phase){case"cloning":return 15;case"applying_fix":return 25;case"fetching_trunk":return 35;case"rebasing":case"merging":return 45;case"resolving_conflicts":return Math.min(90,55+(((t=r.recentActivity)==null?void 0:t.length)??0)*3);case"verifying":return 92;case"pushing":return 96;default:return 20}}function L({children:s}){return e.jsx("div",{className:"px-4 pb-1 pt-3 text-xs font-semibold uppercase tracking-wide text-gray-400",children:s})}const ve={high:"bg-green-100 text-green-700 dark:bg-green-950/40 dark:text-green-300",medium:"bg-amber-100 text-amber-700 dark:bg-amber-950/40 dark:text-amber-300",low:"bg-red-100 text-red-700 dark:bg-red-950/40 dark:text-red-300"};function G({label:s,value:r}){return r?e.jsxs("span",{className:`rounded px-1.5 py-0.5 text-[10px] font-medium uppercase ${ve[r]}`,title:s==="Fixability"?"How confident the analysis is that Pierre's agent could fix this":"How confident the analysis is about the root cause",children:[s,": ",r]}):null}function De({pr:s}){const{aiAnalysis:r,aiFix:t}=te(),n=W(x=>x.aiFixTabFocus),i=W(x=>x.consumeAiFixTabFocus),[c,m]=o.useState(null);return o.useEffect(()=>{n&&n.prId===s.id&&(n.reviewText&&m(n.reviewText),i())},[n,s.id,i]),!r&&!t?e.jsx("div",{className:"p-4 text-sm text-gray-500",children:"AI Analysis and Fix is not enabled."}):e.jsxs("div",{className:"pb-6",children:[r&&e.jsx("div",{className:"border-b border-gray-200 dark:border-gray-800",children:e.jsx(re,{pr:s})}),e.jsx(Ce,{pr:s}),r&&e.jsx(Pe,{pr:s,canFix:t}),t&&e.jsx(Re,{pr:s,seedReviewText:c,onSeedConsumed:()=>m(null)})]})}function Ce({pr:s}){const r=s.checkRuns;return r.length===0?null:e.jsxs("div",{className:"border-b border-gray-200 dark:border-gray-800",children:[e.jsx(L,{children:"CI status"}),e.jsxs("div",{className:"px-4 pb-3",children:[e.jsx(ne,{prId:s.id,checks:r}),e.jsx(ae,{prId:s.id,checks:r,viewerCanPush:s.viewerCanPush})]})]})}function Pe({pr:s,canFix:r}){const{data:t}=ie(s.id,!0),n=ce(s.id),i=J(s.id),c=o.useMemo(()=>s.checkRuns.filter(l=>l.state==="failure"||l.state==="error").map(l=>({name:l.name,jobId:l.jobId,state:l.state})),[s.checkRuns]);if(!(c.length>0||((t==null?void 0:t.hasFailures)??!1))&&!(t!=null&&t.analysis))return null;const x=(t==null?void 0:t.fixability)==="low";return e.jsxs("div",{className:"border-b border-gray-200 dark:border-gray-800",children:[e.jsx(L,{children:"CI failure analysis"}),e.jsxs("div",{className:"px-4 pb-3",children:[(t==null?void 0:t.analysis)&&(t.rootCauseConfidence||t.fixability)&&e.jsxs("div",{className:"mb-1.5 flex flex-wrap items-center gap-1.5",children:[e.jsx("span",{className:"text-[10px] font-semibold uppercase tracking-wide text-gray-400",title:"How confident the analysis is — not a severity rating",children:"Confidence"}),e.jsx(G,{label:"Root cause",value:t.rootCauseConfidence}),e.jsx(G,{label:"Fixability",value:t.fixability})]}),t!=null&&t.analysis?e.jsx("div",{className:"prose prose-sm max-w-none dark:prose-invert",children:e.jsx(K,{children:t.analysis})}):e.jsx("p",{className:"text-sm text-gray-500",children:"Diagnose the failing CI: likely root cause + a suggested fix, from the full logs of every failing check."}),e.jsxs("div",{className:"mt-2 flex flex-wrap items-center gap-2",children:[e.jsx("button",{type:"button",className:j,disabled:n.isPending||c.length===0,onClick:()=>n.mutate(c),children:n.isPending?"Analyzing…":t!=null&&t.analysis?"Re-analyze":"Analyze CI failure"}),r&&(t==null?void 0:t.analysis)&&e.jsx("button",{type:"button",className:S,disabled:i.isPending,onClick:()=>i.mutate({model:"claude-sonnet-5",seed:"ci_analysis"}),title:"Launch an agent to fix the CI failure",children:"Fix it →"}),r&&x&&(t==null?void 0:t.analysis)&&e.jsx("span",{className:"text-[11px] text-gray-500",children:"low confidence this is auto-fixable"}),n.isError&&e.jsx("span",{className:"text-[11px] text-red-500",children:D(n.error)})]})]})]})}function Re({pr:s,seedReviewText:r,onSeedConsumed:t}){var k,F,N,A;const{data:n,isLoading:i}=le(s.id,!0),[c,m]=o.useState("claude-sonnet-5"),x=J(s.id),l=oe(s.id),p=((k=n==null?void 0:n.fix)==null?void 0:k.status)??null,h=p==="running"||p==="queued"||x.isPending,{status:d}=de(s.id,h),R=(d==null?void 0:d.status)??p??"idle",f=R==="running"||R==="queued",w=r?"review":"plain",M=()=>{x.mutate({model:c,seed:w,reviewText:r??void 0},{onSuccess:()=>t()})},u=(n==null?void 0:n.fix)??null;return e.jsxs("div",{children:[e.jsx(L,{children:"AI Fix"}),e.jsxs("div",{className:"px-4",children:[(n==null?void 0:n.enabled)===!1?e.jsx("p",{className:"text-sm text-gray-500",children:"The agentic fixer is disabled."}):(n==null?void 0:n.auth)==="none"?e.jsx("p",{className:"rounded border border-amber-300 bg-amber-50 p-2 text-xs text-amber-700 dark:border-amber-700 dark:bg-amber-950/30 dark:text-amber-300",children:n.authMessage??"No Claude authentication found. Sign in to Claude or set an API key, then restart."}):e.jsxs(e.Fragment,{children:[r&&!f&&e.jsx("div",{className:"mb-2 rounded border border-blue-200 bg-blue-50 p-2 text-xs text-blue-700 dark:border-blue-800 dark:bg-blue-950/30 dark:text-blue-300",children:"Ready to generate a fix from the selected review."}),e.jsxs("div",{className:"flex flex-wrap items-center gap-2",children:[e.jsx("select",{className:"rounded border border-gray-300 bg-transparent px-2 py-1 text-xs dark:border-gray-700",value:c,onChange:y=>m(y.target.value),disabled:f,children:ue.map(y=>e.jsx("option",{value:y,children:xe[y]},y))}),f?e.jsx("button",{type:"button",className:j,onClick:()=>l.mutate(),children:"Cancel"}):e.jsx("button",{type:"button",className:S,disabled:x.isPending,onClick:M,children:u?"Generate new fix":"Generate fix"}),x.isError&&e.jsx("span",{className:"text-[11px] text-red-500",children:D(x.error)})]}),f&&e.jsxs("div",{className:"mt-3",children:[e.jsx(Q,{active:!0,label:"Running AI fix",value:je(d),timeConstantSec:40}),e.jsx("div",{className:"mt-1 text-[11px] text-gray-500",children:ye[((F=d==null?void 0:d.progress)==null?void 0:F.phase)??""]??"Working…"}),((N=d==null?void 0:d.progress)==null?void 0:N.recentActivity)&&d.progress.recentActivity.length>0&&e.jsx("pre",{className:"mt-1 max-h-32 overflow-auto rounded bg-gray-50 p-2 text-[11px] leading-relaxed text-gray-500 dark:bg-gray-900",children:d.progress.recentActivity.slice(-8).join(`
|
|
2
2
|
`)})]}),!f&&u&&e.jsx(we,{pr:s,fix:u,headInfo:(n==null?void 0:n.headInfo)??null,viewerCanPush:(n==null?void 0:n.viewerCanPush)??!1}),i&&!u&&e.jsx("p",{className:"mt-3 text-xs text-gray-400",children:"Loading…"})]}),e.jsx(Fe,{history:(n==null?void 0:n.history)??[],currentFixId:((A=n==null?void 0:n.fix)==null?void 0:A.id)??null})]})]})}function we({pr:s,fix:r,headInfo:t,viewerCanPush:n}){const i=o.useMemo(()=>X(r.patch),[r.patch]);if(r.status==="failed")return e.jsxs("div",{className:"mt-3 rounded border border-red-200 bg-red-50 p-2 text-xs text-red-700 dark:border-red-800 dark:bg-red-950/30 dark:text-red-300",children:["The fix run failed: ",r.error??"unknown error"]});if(r.status==="cancelled")return e.jsx("p",{className:"mt-3 text-xs text-gray-500",children:"The fix run was cancelled."});if(r.status!=="succeeded")return e.jsx(e.Fragment,{});const c=!r.patch||r.filesChanged.length===0;return e.jsxs("div",{className:"mt-3",children:[r.summary&&e.jsx("div",{className:"prose prose-sm max-w-none dark:prose-invert",children:e.jsx(K,{children:r.summary})}),c?e.jsx("p",{className:"mt-2 text-xs text-gray-500",children:"The agent made no changes."}):e.jsxs(e.Fragment,{children:[e.jsxs("div",{className:"mb-1 mt-2 text-[11px] text-gray-500",children:[r.filesChanged.length," file",r.filesChanged.length===1?"":"s"," changed"]}),e.jsx("div",{className:"overflow-hidden rounded border border-gray-200 text-gray-800 dark:border-gray-800 dark:text-gray-200",children:e.jsx(Z,{files:i})}),e.jsx(Se,{pr:s,fix:r,headInfo:t,viewerCanPush:n})]})]})}function _({fix:s}){return e.jsxs("div",{className:"mb-2 rounded border border-green-200 bg-green-50 p-2 text-xs text-green-700 dark:border-green-800 dark:bg-green-950/30 dark:text-green-300",children:[e.jsxs("div",{children:["Pushed to ",e.jsx("span",{className:"font-mono",children:s.pushedBranch}),s.pushedPrUrl&&e.jsxs(e.Fragment,{children:[" · ",e.jsxs("a",{href:s.pushedPrUrl,target:"_blank",rel:"noreferrer",className:"underline",children:["PR #",s.pushedPrNumber]})]}),s.pushedAt&&e.jsxs(e.Fragment,{children:[" · ",I(s.pushedAt)]})]}),s.commitMessage&&e.jsx("div",{className:"mt-1 font-mono text-[11px] text-green-800 dark:text-green-300",children:s.commitMessage})]})}function Fe({history:s,currentFixId:r}){const t=s.filter(n=>n.pushedAt!=null&&n.id!==r);return t.length===0?null:e.jsxs("div",{className:"mt-4 border-t border-gray-200 pt-3 dark:border-gray-800",children:[e.jsx("div",{className:"mb-1.5 text-xs font-semibold uppercase tracking-wide text-gray-400",children:"Fixes pushed via Pierre"}),e.jsx("ul",{className:"space-y-2",children:t.map(n=>e.jsxs("li",{className:"text-xs",children:[e.jsx("div",{className:"font-mono text-gray-700 dark:text-gray-200",children:n.commitMessage??"(no commit message)"}),e.jsxs("div",{className:"mt-0.5 text-[11px] text-gray-400",children:[n.pushedBranch&&e.jsx("span",{className:"font-mono",children:n.pushedBranch}),n.pushedPrUrl&&e.jsxs(e.Fragment,{children:[" · ",e.jsxs("a",{href:n.pushedPrUrl,target:"_blank",rel:"noreferrer",className:"underline",children:["PR #",n.pushedPrNumber]})]}),n.pushedAt&&e.jsxs(e.Fragment,{children:[" · ",I(n.pushedAt)]})]})]},n.id))})]})}function Ae({preview:s,loading:r}){if(r)return e.jsx("p",{className:"text-[11px] text-gray-400",children:"Checking against the trunk…"});if(!s||!s.available||!s.trunkSha)return null;if(!s.clean){const t=s.conflictFiles;return e.jsxs("div",{className:"rounded border border-amber-300 bg-amber-50 p-2 text-[11px] text-amber-700 dark:border-amber-700 dark:bg-amber-950/30 dark:text-amber-300",children:["⚠ Conflicts with ",e.jsx("span",{className:"font-mono",children:s.trunk}),t.length>0?e.jsxs(e.Fragment,{children:[" in ",t.length," file",t.length===1?"":"s",e.jsxs("span",{className:"text-amber-600/90 dark:text-amber-400/90",children:[": ",t.slice(0,6).join(", "),t.length>6?"…":""]})]}):null,". Resolving before you push avoids a conflicted PR."]})}return s.behindBy>0?e.jsxs("p",{className:"text-[11px] text-gray-500",children:[e.jsx("span",{className:"font-mono",children:s.trunk})," is ",s.behindBy," ","commit",s.behindBy===1?"":"s"," ahead — the fix merges cleanly."]}):e.jsxs("p",{className:"text-[11px] text-green-600 dark:text-green-400",children:["Up to date with ",e.jsx("span",{className:"font-mono",children:s.trunk})," — no conflicts."]})}function Ee({resolved:s,target:r,pushing:t,onPush:n,onRedo:i,disabled:c}){const m=o.useMemo(()=>X(s.diff),[s.diff]);return e.jsxs("div",{className:"mt-2 space-y-2",children:[e.jsxs("div",{className:"rounded border border-green-200 bg-green-50 p-2 text-[11px] text-green-700 dark:border-green-800 dark:bg-green-950/30 dark:text-green-300",children:["Rebased onto ",e.jsx("span",{className:"font-mono",children:s.trunk}),".",s.resolvedConflicts?` Claude resolved conflicts in ${s.conflictFiles.length} file${s.conflictFiles.length===1?"":"s"}${s.conflictFiles.length?`: ${s.conflictFiles.join(", ")}`:""}.`:" No conflicts."," ","Review the result below, then push."]}),e.jsxs("div",{className:"text-[11px] text-gray-500",children:[s.filesChanged.length," file",s.filesChanged.length===1?"":"s"," in the rebased result"]}),e.jsx("div",{className:"overflow-hidden rounded border border-gray-200 text-gray-800 dark:border-gray-800 dark:text-gray-200",children:e.jsx(Z,{files:m})}),e.jsxs("div",{className:"flex flex-wrap items-center gap-2",children:[e.jsx("button",{type:"button",className:S,disabled:t||c,onClick:n,children:t?"Pushing…":r==="new"?"Push rebased + open PR":"Push rebased (force-with-lease)"}),e.jsx("button",{type:"button",className:j,disabled:t,onClick:i,children:"Re-rebase"})]})]})}function Se({pr:s,fix:r,headInfo:t,viewerCanPush:n}){var V,z;const i=ge(s.id),c=me(),m=be(),x=pe(),l=fe(),p=(t==null?void 0:t.canPushSameBranch)??!1,[h,d]=o.useState(p?"existing":"new"),[R,f]=o.useState((t==null?void 0:t.suggestedBranch)??""),[w,M]=o.useState(!0),[u,k]=o.useState("idle"),[F,N]=o.useState(null),A=o.useRef(!1),y=o.useRef(!1);o.useEffect(()=>{!A.current&&(t!=null&&t.suggestedBranch)&&(f(t.suggestedBranch),A.current=!0,t.canPushSameBranch||d("new"))},[t]);const g=r.pushedAt!=null,q=g&&r.pushedPrNumber==null,O=!g||q;o.useEffect(()=>{!y.current&&n&&O&&(y.current=!0,l.mutate(r.id))},[n,O,r.id]);const a=l.data??null,{status:v}=Y(s.id,r.id,"rebase",u==="rebasing"),{status:C}=Y(s.id,r.id,"push",u==="pushing");if(o.useEffect(()=>{u==="rebasing"&&v&&v.status!=="running"&&v.status!=="queued"&&(k("idle"),v.error&&N(v.error))},[u,v]),o.useEffect(()=>{u==="pushing"&&C&&C.status!=="running"&&C.status!=="queued"&&(k("idle"),C.error&&N(C.error))},[u,C]),!n)return g?e.jsx(_,{fix:r}):e.jsx("p",{className:"mt-2 text-xs text-gray-500",children:"You need write access to this repository to push this fix."});if(g&&!q)return e.jsx(_,{fix:r});const B=h==="new"&&R.trim().length===0,P=u!=="idle"||i.isPending||c.isPending,U=r.model,ee=g&&!!a&&a.available&&a.clean&&a.behindBy===0,T=E=>{N(null),i.mutate({fixId:r.id,body:{target:h,branch:h==="new"?R.trim():void 0,strategy:E,autoResolve:w,model:U}},{onSuccess:se=>{"pushedBranch"in se||k("pushing")}})},H=()=>{N(null),c.mutate({fixId:r.id,body:{autoResolve:w,model:U}},{onSuccess:()=>k("rebasing")})},b=u==="rebasing"?v:C,$=r.resolved;return e.jsxs("div",{className:"mt-3 rounded border border-gray-200 p-2 dark:border-gray-800",children:[g&&e.jsx(_,{fix:r}),e.jsx("div",{className:"mb-2 text-xs font-semibold text-gray-600 dark:text-gray-300",children:g?"Reconcile with the trunk":"Push this fix"}),!g&&r.commitMessage&&e.jsxs("div",{className:"mb-2 rounded bg-gray-50 p-2 text-[11px] dark:bg-gray-900",children:[e.jsx("span",{className:"uppercase tracking-wide text-gray-400",children:"Commit message"}),e.jsx("div",{className:"mt-0.5 font-mono text-gray-700 dark:text-gray-200",children:r.commitMessage})]}),e.jsxs("label",{className:`flex items-center gap-2 text-xs ${p?"":"opacity-40"}`,title:p?void 0:"The PR head is a fork you cannot push to — use a new branch",children:[e.jsx("input",{type:"radio",checked:h==="existing",disabled:!p||P,onChange:()=>d("existing")}),"Push to the PR branch",(t==null?void 0:t.headRef)&&e.jsxs("span",{className:"font-mono text-gray-400",children:["(",t.headRef,")"]})]}),e.jsxs("label",{className:"mt-1 flex items-center gap-2 text-xs",children:[e.jsx("input",{type:"radio",checked:h==="new",disabled:P,onChange:()=>d("new")}),"New branch + open a PR"]}),h==="new"&&e.jsx("input",{type:"text",className:"mt-1 w-full rounded border border-gray-300 bg-transparent px-2 py-1 font-mono text-xs dark:border-gray-700",value:R,disabled:P,onChange:E=>f(E.target.value),placeholder:"branch-name"}),e.jsxs("div",{className:"mt-2 flex flex-wrap items-center gap-2",children:[e.jsx("div",{className:"min-w-0 flex-1",children:e.jsx(Ae,{preview:a,loading:l.isPending})}),e.jsx("button",{type:"button",className:j,disabled:l.isPending||P,onClick:()=>l.mutate(r.id),title:"Re-check this fix against the current trunk",children:l.isPending?"Checking…":"Re-check trunk"}),l.isError&&!l.isPending&&e.jsx("span",{className:"text-[11px] text-red-500",children:"Couldn't check the trunk — try again."})]}),u!=="idle"?e.jsxs("div",{className:"mt-2",children:[e.jsx(Q,{active:!0,label:u==="rebasing"?"Rebasing & resolving":"Pushing",value:Ne(b),timeConstantSec:40}),e.jsxs("div",{className:"mt-1 flex items-center gap-2 text-[11px] text-gray-500",children:[e.jsx("span",{children:ke[((V=b==null?void 0:b.progress)==null?void 0:V.phase)??""]??"Working…"}),e.jsx("button",{type:"button",className:j,onClick:()=>u==="rebasing"?m.mutate(r.id):x.mutate(r.id),children:"Cancel"})]}),((z=b==null?void 0:b.progress)==null?void 0:z.recentActivity)&&b.progress.recentActivity.length>0&&e.jsx("pre",{className:"mt-1 max-h-32 overflow-auto rounded bg-gray-50 p-2 text-[11px] leading-relaxed text-gray-500 dark:bg-gray-900",children:b.progress.recentActivity.slice(-8).join(`
|
|
3
3
|
`)})]}):$?e.jsx(Ee,{resolved:$,target:h,pushing:i.isPending,disabled:B,onPush:()=>T("rebase"),onRedo:H}):ee?e.jsxs("p",{className:"mt-2 text-[11px] text-gray-500",children:["No trunk changes to reconcile — the pushed fix is up to date with"," ",e.jsx("span",{className:"font-mono",children:a==null?void 0:a.trunk}),"."]}):e.jsxs("div",{className:"mt-2 space-y-2",children:[a&&a.available&&!a.clean&&e.jsxs("div",{className:"text-[11px] text-gray-500",children:["Recommended: rebase onto"," ",e.jsx("span",{className:"font-mono",children:a.trunk})," — Claude resolves the conflicts and you review the result before it pushes."]}),e.jsxs("label",{className:"flex items-center gap-2 text-[11px] text-gray-600 dark:text-gray-300",children:[e.jsx("input",{type:"checkbox",checked:w,onChange:E=>M(E.target.checked)}),"Let Claude resolve conflicts"]}),e.jsxs("div",{className:"flex flex-wrap items-center gap-2",children:[e.jsxs("button",{type:"button",className:a&&!a.clean?S:j,disabled:P||B,onClick:H,title:"Rebase the fix onto the trunk; Claude resolves conflicts and you review before a force-with-lease push",children:["Rebase onto ",(a==null?void 0:a.trunk)??"trunk"]}),!g&&e.jsxs("button",{type:"button",className:j,disabled:P||B,onClick:()=>T("merge"),title:"Merge the trunk into the fix branch (a merge commit; never force-pushes)",children:["Merge ",(a==null?void 0:a.trunk)??"trunk"," in"]}),!g&&e.jsxs("button",{type:"button",className:!a||a.clean?S:j,disabled:P||B,onClick:()=>T("plain"),title:"Push the fix as-is (never force-pushes). If it conflicts with the trunk, the PR will show as conflicted.",children:[h==="new"?"Push + open PR":"Push",a&&!a.clean?" anyway":""]})]}),g&&e.jsxs("p",{className:"text-[11px] text-gray-400",children:["Rebasing replays the fix onto"," ",e.jsx("span",{className:"font-mono",children:(a==null?void 0:a.trunk)??"the trunk"})," ","and force-pushes (with lease) onto the PR branch — the safe way to reconcile an already-pushed fix."]}),h==="existing"&&e.jsxs("p",{className:"text-[11px] text-gray-400",children:["Rebase force-pushes (with lease) onto"," ",e.jsx("span",{className:"font-mono",children:t==null?void 0:t.headRef}),"; merge and push do not."]})]}),(F||i.isError||c.isError)&&e.jsx("div",{className:"mt-2 text-[11px] text-red-500",children:F??D(i.error??c.error)})]})}function D(s){return s instanceof he||s instanceof Error?s.message:"Something went wrong"}export{De as AiFixTab};
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import{e as be,r as c,j as e}from"./tanstack-R-s9abdD.js";import{f as ye,w as we,B as Ce,t as Re,Q as Pe,P as Se,G as Ee,E as Te,y as Ae,x as $e,C as Fe,b as Ie,R as _e,j as fe,i as se,e as ve,I as re,z as Be,u as Me,L as Le,M as ee}from"./index-
|
|
1
|
+
import{e as be,r as c,j as e}from"./tanstack-R-s9abdD.js";import{f as ye,w as we,B as Ce,t as Re,Q as Pe,P as Se,G as Ee,E as Te,y as Ae,x as $e,C as Fe,b as Ie,R as _e,j as fe,i as se,e as ve,I as re,z as Be,u as Me,L as Le,M as ee}from"./index-XM1NIyvh.js";import"./markdown-BUNN1sk6.js";import"./highlight-C8vPehS1.js";import"./vis-C3BCkP5U.js";function He(t,s){return be({queryKey:["review-learnings",t],queryFn:()=>ye.reviewLearnings(t),enabled:s&&t!=null})}function Oe(t,s){return be({queryKey:["review-actions",t],queryFn:()=>ye.reviewActions(t),enabled:s&&t!=null})}function De({label:t,children:s}){return e.jsxs("div",{className:"flex gap-3 px-4 py-1.5 text-sm",children:[e.jsx("span",{className:"w-28 shrink-0 text-xs uppercase tracking-wide text-gray-400",children:t}),e.jsx("div",{className:"min-w-0 flex-1",children:s})]})}const Z=t=>t?t.slice(0,7):"—",z={skip:"Skipped",diff_only:"Quick",worktree:"Deep"},Ve=[{value:"auto",label:"Auto (router decides)"},{value:"diff_only",label:"Quick — diff only"},{value:"worktree",label:"Deep — full worktree"}],V=(t,s)=>`${t} ${s}${t===1?"":"s"}`;function Ge(t){const s=t.routeReason;if(!s)return;const n=`${V(s.changedFiles,"file")} · ${V(s.linesChanged,"line")} · ${V(s.dirsTouched,"dir")}`;return s.decidedBy==="user"?`You chose ${z[t.reviewMode??"worktree"]} for this run (${n}).`:s.trippedBy?`Auto chose Deep — ${n}; over the ${s.trippedBy} limit.`:`Auto chose ${z[t.reviewMode??"diff_only"]} — ${n}.`}const te={COMMENT:"Comment",REQUEST_CHANGES:"Request changes",APPROVE:"Approve"},Ue={APPROVE:"bg-green-500/10 text-green-700 dark:text-green-400",REQUEST_CHANGES:"bg-red-500/10 text-red-700 dark:text-red-400",COMMENT:"bg-gray-500/10 text-gray-600 dark:text-gray-300"};function qe({verdict:t}){return e.jsx("span",{className:`inline-flex items-center rounded px-1.5 py-0.5 text-xs font-medium ${Ue[t]}`,children:te[t]})}const me={blocker:0,warning:1,nit:2,question:3,praise:4},Qe={blocker:"bg-red-500/10 text-red-700 dark:text-red-400",warning:"bg-orange-500/10 text-orange-700 dark:text-orange-400",nit:"bg-yellow-500/10 text-yellow-700 dark:text-yellow-500",question:"bg-blue-500/10 text-blue-700 dark:text-blue-400",praise:"bg-green-500/10 text-green-700 dark:text-green-400"};function We(t){const s=[t.model];return t.costUsd!=null&&s.push(`${fe(t.costUsd)} cr`),t.numTurns!=null&&s.push(`${t.numTurns} turns`),t.excludedFiles.length>0&&s.push(`${t.excludedFiles.length} noise files excluded`),s.join(" · ")}const Ye={cloning:"Cloning the worktree",fetching_diff:"Fetching the diff",deciding:"Deciding scope",reviewing:"Reviewing",persisting:"Saving findings"};function Ke(t){var n,a,r;if(t==null)return null;if(t.status==="queued")return 5;const s=(n=t.progress)==null?void 0:n.phase;if(s==null)return 8;switch(s){case"fetching_diff":return 15;case"deciding":return 28;case"cloning":return 42;case"reviewing":{const i=((r=(a=t.progress)==null?void 0:a.recentActivity)==null?void 0:r.length)??0;return Math.min(90,55+i*3)}case"persisting":return 95;default:return null}}function K(t){return t>=1e6?`${(t/1e6).toFixed(1)}M`:t>=1e3?`${(t/1e3).toFixed(1)}k`:String(t)}function ze({review:t}){const{inputTokens:s,outputTokens:n,cacheReadTokens:a,cacheCreationTokens:r}=t;if((s??0)+(n??0)+(a??0)+(r??0)<=0)return null;const d=[];return n!=null&&d.push({key:"out",label:"↓ out",value:n,title:"Output tokens generated (billed at the output rate — the priciest per token)"}),s!=null&&d.push({key:"in",label:"↑ in",value:s,title:"New (uncached) input tokens"}),a!=null&&d.push({key:"cr",label:"⟳ cache read",value:a,title:"Cached input tokens re-read each turn — billed at ~10% of the input rate, but the volume driver of a multi-turn run"}),r!=null&&d.push({key:"cw",label:"✎ cache write",value:r,title:"Tokens written to the prompt cache (billed at ~1.25× the input rate)"}),e.jsx("div",{className:"flex flex-wrap items-center gap-x-3 gap-y-0.5 font-mono text-xs text-gray-500 dark:text-gray-400",children:d.map(o=>e.jsxs("span",{title:o.title,children:[o.label," ",K(o.value)]},o.key))})}function Je({lines:t}){const s=c.useRef(null);return c.useEffect(()=>{const n=s.current;n!=null&&(n.scrollTop=n.scrollHeight)},[t]),t.length===0?null:e.jsx("div",{ref:s,className:"mt-2 max-h-32 overflow-y-auto rounded border border-gray-100 bg-gray-50 px-2 py-1.5 font-mono text-[11px] leading-snug text-gray-500 dark:border-gray-800 dark:bg-gray-900/60 dark:text-gray-400",children:t.map((n,a)=>e.jsx("div",{className:"whitespace-pre-wrap break-words",children:n===""?" ":n},a))})}function ge(t){return t.startsWith("@@")?"text-violet-500":t.startsWith("+")?"text-green-700 dark:text-green-400":t.startsWith("-")?"text-red-700 dark:text-red-400":"text-gray-500 dark:text-gray-400"}const Y="whitespace-nowrap rounded border border-blue-400 px-2 py-0.5 text-xs text-blue-600 hover:bg-blue-50 disabled:opacity-50 dark:border-blue-600 dark:text-blue-400 dark:hover:bg-blue-900/30",B="whitespace-nowrap rounded border border-gray-300 px-2 py-0.5 text-xs hover:border-gray-400 disabled:opacity-50 dark:border-gray-700 dark:hover:border-gray-500";function Xe({hunk:t}){const[s,n]=c.useState(!1),a=t.replace(/\n$/,"").split(`
|
|
2
2
|
`),r=a.find(i=>i.startsWith("@@"))??a.at(-1)??"";return s?e.jsxs("div",{className:"mt-1 rounded bg-gray-50 dark:bg-gray-900/60",children:[e.jsx("pre",{className:"overflow-x-auto px-2 py-1.5 font-mono text-xs leading-snug",children:a.map((i,d)=>e.jsx("div",{className:ge(i),children:i===""?" ":i},d))}),e.jsx("button",{type:"button",onClick:()=>n(!1),className:"px-2 pb-1.5 text-[11px] text-gray-400 hover:text-gray-600 dark:hover:text-gray-300",children:"⌃ Hide code"})]}):e.jsxs("button",{type:"button",onClick:()=>n(!0),title:"Show the code hunk",className:"mt-1 flex w-full items-center gap-2 overflow-hidden rounded bg-gray-50 px-2 py-1.5 text-left font-mono text-xs dark:bg-gray-900/60",children:[e.jsx("span",{className:"shrink-0 text-gray-400",children:"▸"}),e.jsx("span",{className:`min-w-0 flex-1 truncate ${ge(r)}`,children:r===""?" ":r}),a.length>1&&e.jsxs("span",{className:"shrink-0 font-sans text-[10px] text-gray-400",children:[a.length," lines"]})]})}function Ze({prId:t,finding:s,editable:n,prUrl:a,repoFullName:r,headSha:i,posting:d,postError:o,onToggle:b,onReword:k,onPostComment:g}){const[P,E]=c.useState(!1),x=c.useRef(null);c.useEffect(()=>()=>{x.current!=null&&clearTimeout(x.current)},[]);const[p,j]=c.useState(!1),[S,m]=c.useState(s.editedBody??"");c.useEffect(()=>{p||m(s.editedBody??"")},[s.editedBody,p]);const y=s.editedBody!=null&&s.editedBody.trim()!=="",h=p&&S.trim()!==""&&S!==(s.editedBody??"")?S:null,T=h!=null||y,J=h??(y?s.editedBody:s.body),A=s.line!=null?`${s.path}:${s.line}`:s.path,f=s.postedAt!=null,v=s.githubCommentId!=null?s.postedCommentKind==="pr_comment"?`${a}#issuecomment-${s.githubCommentId}`:`${a}#discussion_r${s.githubCommentId}`:null,$=s.line!=null?`${a}/files#diff-${s.diffAnchorId}${s.side==="LEFT"?"L":"R"}${s.line}`:`${a}/files#diff-${s.diffAnchorId}`,G=i!=null&&s.line!=null&&s.side==="RIGHT"?`https://github.com/${r}/blob/${i}/${s.path.split("/").map(encodeURIComponent).join("/")}#L${s.line}`:null,N=v??$,w=v==null?G:null,U=n,q=()=>{let I=`${s.title}
|
|
3
3
|
|
|
4
4
|
${J}`;s.suggestion!=null&&s.suggestion!==""&&(I+=`
|
|
@@ -1 +1 @@
|
|
|
1
|
-
import{j as s}from"./tanstack-R-s9abdD.js";import{H as p,n as m,g,r as x,h as y}from"./index-
|
|
1
|
+
import{j as s}from"./tanstack-R-s9abdD.js";import{H as p,n as m,g,r as x,h as y}from"./index-XM1NIyvh.js";import"./markdown-BUNN1sk6.js";import"./highlight-C8vPehS1.js";import"./vis-C3BCkP5U.js";function o(e){return e==null?"—":y(e)}function d({label:e,value:r,tone:a}){return s.jsxs("div",{children:[s.jsx("div",{className:"text-[9px] font-semibold uppercase tracking-wide text-gray-400",children:e}),s.jsx("div",{className:`text-sm font-semibold ${a==="warn"?"text-red-600 dark:text-red-400":"text-gray-800 dark:text-gray-100"}`,children:r})]})}function h({bot:e,color:r}){const a=g(e.kind),t=e.ttfrAnomaly,n=e.typicalTtfrHours==null,i=e.typicalFollowups!=null&&e.followupCount>=e.typicalFollowups+2,l=n?"building baseline":t?`⚠ slower than typical — ${o(e.ttfrHours)} vs ${o(e.typicalTtfrHours)} typical`:`within typical (${o(e.typicalTtfrHours)})`;return s.jsxs("div",{className:"space-y-2 rounded-lg border border-gray-200 p-3 dark:border-gray-800",children:[s.jsxs("div",{className:"flex flex-wrap items-center gap-2",children:[s.jsxs("span",{className:"inline-flex items-center gap-1.5 text-sm font-semibold text-gray-800 dark:text-gray-100",children:[s.jsx("span",{className:"inline-block h-2.5 w-2.5 rounded-full",style:{background:r},"aria-hidden":!0}),e.label]}),s.jsx("span",{className:"rounded px-1.5 py-0.5 text-[10px] font-medium",style:{color:a.color,background:`${a.color}1a`},children:a.label}),e.firstTouchAt&&s.jsxs("span",{className:"text-[11px] text-gray-400",children:["first touch ",x(e.firstTouchAt)]}),t&&s.jsxs("span",{className:"rounded bg-red-500/10 px-1.5 py-0.5 text-[10px] font-semibold text-red-600 dark:text-red-400",children:["⚠ ",o((e.ttfrHours??0)-(e.typicalTtfrHours??0))," slower than usual"]})]}),s.jsxs("div",{className:"grid grid-cols-2 gap-2 sm:grid-cols-4",children:[s.jsx(d,{label:"Time to first review",value:o(e.ttfrHours),tone:t?"warn":"default"}),s.jsx(d,{label:"Follow-ups",value:String(e.followupCount),tone:i?"warn":"default"}),s.jsx(d,{label:"Comments",value:String(e.commentCount)}),s.jsx(d,{label:"Touches",value:String(e.touchCount)})]}),s.jsxs("div",{className:"text-[11px] text-gray-500 dark:text-gray-400",children:[s.jsx("span",{className:t?"font-medium text-red-600 dark:text-red-400":"",children:l}),e.ttfrBasis&&!n&&s.jsxs("span",{className:"text-gray-400",children:[" · from ",e.ttfrBasis==="ready"?"ready-for-review":"opened"]}),e.typicalFollowups!=null&&s.jsxs("span",{className:"text-gray-400",children:[" · ",e.followupCount," follow-up",e.followupCount===1?"":"s"," vs ",e.typicalFollowups," typical",i?" (more than usual)":""]}),!n&&s.jsxs("span",{className:"text-gray-400",children:[" · baseline: ",e.baselinePrs," PRs"]})]}),e.touches.length>0&&s.jsxs("div",{className:"flex flex-wrap items-center gap-1",children:[e.touches.slice(0,16).map((c,u)=>s.jsxs("span",{className:"inline-flex items-center gap-1 rounded bg-gray-500/10 px-1.5 py-0.5 text-[10px] text-gray-600 dark:text-gray-300",title:new Date(c.at).toLocaleString(),children:[s.jsx("span",{"aria-hidden":!0,children:c.kind==="review"?"📝":"💬"}),x(c.at)]},u)),e.touches.length>16&&s.jsxs("span",{className:"text-[10px] text-gray-400",children:["+",e.touches.length-16," more"]})]})]})}function N({pr:e}){const{data:r,isLoading:a,isError:t}=p(e.id,!0),n=m(),i=(r==null?void 0:r.bots)??[];return s.jsxs("div",{className:"space-y-3 p-4",children:[s.jsxs("div",{className:"flex flex-wrap items-center gap-2",children:[s.jsx("span",{className:"rounded bg-sky-100 px-1.5 py-0.5 text-[10px] font-semibold uppercase tracking-wide text-sky-700 dark:bg-sky-900/40 dark:text-sky-300",children:"Experimental"}),s.jsxs("span",{className:"text-[11px] text-gray-400",children:["How each review bot behaved on THIS PR vs its ",s.jsx("span",{className:"font-medium",children:"own"})," ","typical (84-day baseline). Deterministic, no AI."]})]}),a?s.jsx("div",{className:"h-24 animate-pulse rounded-lg border border-gray-200 bg-gray-50 dark:border-gray-800 dark:bg-gray-900/40"}):t?s.jsx("div",{className:"text-sm text-red-500",children:"Couldn’t load bot behaviour for this PR."}):i.length===0?s.jsx("div",{className:"rounded-lg border border-dashed border-gray-300 p-6 text-center text-sm text-gray-400 dark:border-gray-700",children:"No automated-reviewer activity on this PR."}):i.map(l=>s.jsx(h,{bot:l,color:n({login:l.login,kind:l.kind})},l.key))]})}export{N as PrBotBehaviourTab};
|