pierre-review 0.1.22 → 0.1.24
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/api/routes/claude-review.js +2 -2
- package/dist/api/routes/insights.js +35 -0
- package/dist/api/routes/me.js +4 -2
- package/dist/api/routes/prs.js +16 -1
- package/dist/app.js +2 -0
- package/dist/config.js +9 -2
- package/dist/db/queries.js +611 -5
- package/dist/db/schema.pg.js +3 -1
- package/dist/db/schema.sqlite.js +9 -6
- package/dist/review/agent.js +5 -5
- package/dist/review/clone-manager.js +40 -0
- package/dist/review/review-manager.js +85 -28
- package/package.json +1 -1
- package/public/assets/index-CF5RjHlj.css +10 -0
- package/public/assets/index-_pvZqY4L.js +1371 -0
- package/public/index.html +2 -2
- package/public/assets/index-DmAenjsb.js +0 -1371
- package/public/assets/index-Lropvevu.css +0 -10
|
@@ -154,8 +154,8 @@ export async function claudeReviewRoutes(app) {
|
|
|
154
154
|
return {
|
|
155
155
|
error: 'Conflict',
|
|
156
156
|
message: result.reason === 'already_running'
|
|
157
|
-
? 'A review is already running for this PR.'
|
|
158
|
-
: '
|
|
157
|
+
? 'A review is already running or queued for this PR.'
|
|
158
|
+
: 'The review queue is full; try again once some finish.',
|
|
159
159
|
};
|
|
160
160
|
}
|
|
161
161
|
reply.status(202);
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
import { getInsights, getRepoAnalytics } from '../../db/queries.js';
|
|
2
|
+
import { accountIdOf } from '../plugins/auth.js';
|
|
3
|
+
function parseIntList(raw) {
|
|
4
|
+
if (!raw)
|
|
5
|
+
return null;
|
|
6
|
+
const ids = raw
|
|
7
|
+
.split(',')
|
|
8
|
+
.map((s) => Number.parseInt(s.trim(), 10))
|
|
9
|
+
.filter((n) => Number.isFinite(n));
|
|
10
|
+
return ids.length > 0 ? ids : null;
|
|
11
|
+
}
|
|
12
|
+
export async function insightsRoutes(app) {
|
|
13
|
+
// Per-repo sprint/team stats for the Insights panel. Scoped to the account;
|
|
14
|
+
// `repoIds` narrows to the active watched-repo selection.
|
|
15
|
+
app.get('/api/insights', async (req) => {
|
|
16
|
+
const q = req.query;
|
|
17
|
+
return getInsights({
|
|
18
|
+
accountId: accountIdOf(req),
|
|
19
|
+
repoIds: parseIntList(q.repoIds),
|
|
20
|
+
});
|
|
21
|
+
});
|
|
22
|
+
// Heavier per-repo analytics for the drill-down chart panel — loaded on demand.
|
|
23
|
+
// Ownership-scoped: a repo not owned by the account 404s.
|
|
24
|
+
app.get('/api/insights/:repoId/analytics', async (req, reply) => {
|
|
25
|
+
const { repoId } = req.params;
|
|
26
|
+
const id = Number.parseInt(repoId, 10);
|
|
27
|
+
const data = Number.isFinite(id)
|
|
28
|
+
? await getRepoAnalytics(accountIdOf(req), id)
|
|
29
|
+
: null;
|
|
30
|
+
if (!data)
|
|
31
|
+
return reply.code(404).send({ error: 'repo not found' });
|
|
32
|
+
return data;
|
|
33
|
+
});
|
|
34
|
+
}
|
|
35
|
+
//# sourceMappingURL=insights.js.map
|
package/dist/api/routes/me.js
CHANGED
|
@@ -8,7 +8,7 @@ const dismissSchema = {
|
|
|
8
8
|
required: ['kind', 'refId'],
|
|
9
9
|
additionalProperties: false,
|
|
10
10
|
properties: {
|
|
11
|
-
kind: { type: 'string', enum: ['review_request', 'thread'] },
|
|
11
|
+
kind: { type: 'string', enum: ['review_request', 'thread', 'claude_review'] },
|
|
12
12
|
refId: { type: 'integer' },
|
|
13
13
|
},
|
|
14
14
|
},
|
|
@@ -23,6 +23,7 @@ export async function meRoutes(app) {
|
|
|
23
23
|
awaitingReview: myTurn.awaitingReview.length,
|
|
24
24
|
yourPrsActivity: myTurn.yourPrs.length,
|
|
25
25
|
threadsAwaiting: myTurn.threadsAwaiting.length,
|
|
26
|
+
claudeReviewsToAction: myTurn.claudeReviewsToAction.length,
|
|
26
27
|
},
|
|
27
28
|
claudeReviewEnabled: config.claudeReviewEnabled,
|
|
28
29
|
deploymentMode: config.deploymentMode,
|
|
@@ -34,7 +35,8 @@ export async function meRoutes(app) {
|
|
|
34
35
|
await dismissMyTurn(accountIdOf(req), kind, refId);
|
|
35
36
|
return { status: 'ok' };
|
|
36
37
|
});
|
|
37
|
-
// The "Done" tab: entries dismissed in the past 90 days (review_request + thread
|
|
38
|
+
// The "Done" tab: entries dismissed in the past 90 days (review_request + thread
|
|
39
|
+
// + claude_review).
|
|
38
40
|
app.get('/api/my-turn/done', async (req) => getCompletedDismissals(accountIdOf(req), 90));
|
|
39
41
|
// Un-dismiss: move a completed entry back to the inbox.
|
|
40
42
|
app.post('/api/my-turn/undismiss', { schema: dismissSchema }, async (req) => {
|
package/dist/api/routes/prs.js
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { getPrDetail, markPrViewed } from '../../db/queries.js';
|
|
1
|
+
import { getPrDetail, markAllViewed, markPrViewed } from '../../db/queries.js';
|
|
2
2
|
import { hydratePrDetail } from '../../sync/hydrate-detail.js';
|
|
3
3
|
import { accountIdOf } from '../plugins/auth.js';
|
|
4
4
|
const idParamSchema = {
|
|
@@ -16,7 +16,22 @@ const markViewedSchema = {
|
|
|
16
16
|
properties: { sha: { type: 'string' } },
|
|
17
17
|
},
|
|
18
18
|
};
|
|
19
|
+
const markAllViewedSchema = {
|
|
20
|
+
body: {
|
|
21
|
+
type: 'object',
|
|
22
|
+
additionalProperties: false,
|
|
23
|
+
properties: { repoIds: { type: 'array', items: { type: 'integer' } } },
|
|
24
|
+
},
|
|
25
|
+
};
|
|
19
26
|
export async function prRoutes(app) {
|
|
27
|
+
// Bulk "mark all seen": stamp every open PR (optionally scoped to repoIds) viewed
|
|
28
|
+
// at its head, clearing all new-since badges at once. Static path — no :id — so it
|
|
29
|
+
// doesn't collide with /api/prs/:id.
|
|
30
|
+
app.post('/api/prs/mark-all-viewed', { schema: markAllViewedSchema }, async (req) => {
|
|
31
|
+
const { repoIds } = (req.body ?? {});
|
|
32
|
+
const count = await markAllViewed(accountIdOf(req), repoIds && repoIds.length > 0 ? repoIds : null);
|
|
33
|
+
return { status: 'ok', count };
|
|
34
|
+
});
|
|
20
35
|
app.get('/api/prs/:id', { schema: idParamSchema }, async (req, reply) => {
|
|
21
36
|
const { id } = req.params;
|
|
22
37
|
const accountId = accountIdOf(req);
|
package/dist/app.js
CHANGED
|
@@ -16,6 +16,7 @@ import { threadRoutes } from './api/routes/threads.js';
|
|
|
16
16
|
import { meRoutes } from './api/routes/me.js';
|
|
17
17
|
import { openPrsRoutes } from './api/routes/open-prs.js';
|
|
18
18
|
import { mergersRoutes } from './api/routes/mergers.js';
|
|
19
|
+
import { insightsRoutes } from './api/routes/insights.js';
|
|
19
20
|
import { claudeReviewRoutes } from './api/routes/claude-review.js';
|
|
20
21
|
export async function buildApp() {
|
|
21
22
|
const app = Fastify({
|
|
@@ -126,6 +127,7 @@ export async function buildApp() {
|
|
|
126
127
|
await app.register(meRoutes);
|
|
127
128
|
await app.register(openPrsRoutes);
|
|
128
129
|
await app.register(mergersRoutes);
|
|
130
|
+
await app.register(insightsRoutes);
|
|
129
131
|
// Claude Review is local-only + opt-in. Only register its routes when enabled,
|
|
130
132
|
// so the clone-manager / gh-CLI dependency is unreachable in cloud mode.
|
|
131
133
|
if (config.claudeReviewEnabled)
|
package/dist/config.js
CHANGED
|
@@ -126,8 +126,15 @@ export const config = {
|
|
|
126
126
|
// Turn cap for a diff-only run. These are TOOL-LESS (only submit_review), so they
|
|
127
127
|
// should finish in ~2 turns; a tight cap is a cheap runaway guard.
|
|
128
128
|
reviewDiffOnlyMaxTurns: intFromEnv('REVIEW_DIFF_ONLY_MAX_TURNS', 6),
|
|
129
|
-
// At most one review per PR; this caps concurrent reviews across all PRs.
|
|
130
|
-
|
|
129
|
+
// At most one review per PR; this caps concurrent reviews across all PRs. Default
|
|
130
|
+
// 4 so the user can bulk-review (extras queue, see review-manager). Raising this
|
|
131
|
+
// also DISABLES the pasted-key override (which mutates process.env and is only
|
|
132
|
+
// safe at concurrency 1 — see local-settings.applyUserAnthropicKey); ambient auth
|
|
133
|
+
// is used instead. Set REVIEW_CONCURRENCY=1 to restore the pasted-key path.
|
|
134
|
+
reviewConcurrency: intFromEnv('REVIEW_CONCURRENCY', 4),
|
|
135
|
+
// Hard ceiling on QUEUED (not-yet-started) reviews, a runaway guard for bulk
|
|
136
|
+
// triggering; further starts return 'busy' until the queue drains.
|
|
137
|
+
reviewMaxQueued: intFromEnv('REVIEW_MAX_QUEUED', 50),
|
|
131
138
|
// ---- Claude Review routing (diff-only vs worktree) — THE THRESHOLDS ----
|
|
132
139
|
// The deterministic pre-check (review/routing.ts) decides, BEFORE the agent runs,
|
|
133
140
|
// whether a PR can be reviewed from its diff alone (fast, tool-less, no worktree)
|